Форум: "Основная";
Текущий архив: 2004.02.17;
Скачать: [xml.tar.bz2];
ВнизКак правильно присвоить PChar переменной String Найти похожие ветки
← →
Genry (2004-02-06 21:31) [0]Доброго времени суток.
У меня есть библиотека, в которой я присваиваю переменной типа String переменную PChar
Делаю это просто
MyStringVar:=MyPCharVar;
при этом если эту библиотеку подключить к приложению созданному на Дельфи, то все замечательно работает.
Если же мою библиотеку вызывает приложение написанное на OracleForms, то именно на этой строчке оно просто вылетает. Без слов и сообщений об ошибках. Причем проверял, переменная MyPCharVar не равна nil.
Подскажите, в чем может быть ошибка ?
← →
jack128 (2004-02-06 21:38) [1]для гарантии скопируй содержимое MyPCharVar
SetLength(MyStringVar, StrLen(MyPCharVar));
move(MyPCharVar^, PChar(MyStringVar)^, Length(MyStringVar));
Проблемы, вероятно из-за разных менеджеров памяти
← →
Genry (2004-02-06 21:52) [2]Спасибо, попробую.
А еще вопрос. Если у меня библиотечная процедура принимает параметр типа PCHar и предполагается, что она его будет изменять , т.е. что-то вроде OUT-параметра, то в процедуре ее нужно объявлять как var MyPCharVar: PChar или var не надо ?
← →
jack128 (2004-02-06 21:57) [3]А у тя что, есть выбор? Как она объявлена в библиотке, так и ты объявляй. Обычно указатель передают по значению..
← →
Genry (2004-02-06 22:07) [4]
> jack128 © (06.02.04 21:57) [3]
Нет, ты не понял. Библиотеку пишу я. И я создаю эту процедуру, в которую потом кто-то будет передавать PCHar в надежде что она ему что-то вернет. Потому и спрашиваю, мне в библиотечной процедуре стоит объявить переменную как var или без var ?
> Обычно указатель передают по значению..
По значению это значит без var ?
(извини за глупый вопрос :))
← →
jack128 (2004-02-06 22:10) [5]
> По значению это значит без var ?
да
← →
Genry (2004-02-06 22:14) [6]
> jack128 © (06.02.04 22:10) [5]
Спасибо !
И еще маленький вопрос. Есть другая процедура, там не в String надо переводить а в WideString. Твой вариант с move там тоже применим ?
← →
jack128 (2004-02-06 22:24) [7]вообще если ты пишешь свою библиотеку на Delphi и используешь её в Delphi то можно передовать строки, только внимательно прочитай коментарий при создании библиотеки.
> Твой вариант с move там тоже применим ?
гм. Move - это копирование участка памяти. Но вероятно тебе нужно не только копировать память, но и перевести в Ansii. Тогда используй MultiByteToWideChar (пример см в StringToWideChar)
← →
jack128 (2004-02-06 22:25) [8]Если перевод в анси не нужен, то, конечно, Move можно использовать..
← →
nikkie (2004-02-07 03:12) [9]>Если же мою библиотеку вызывает приложение написанное на OracleForms, то именно на этой строчке оно просто вылетает.
значит OracleForms передает не PChar. вот и все. какие есть основания полагать, что OracleForms передает указатель на char, или двойной указатель на char, или указатель на какую-нибудь структуру? документация на эту тему что говорит?
Причем проверял, переменная MyPCharVar не равна nil.
сие говорит лишь о том, что OracleForms что-то передает. если посмотреть область памяти куда этот-то указатель указывает, то вероятнее всего окажется, что там лежит не передаваемая строчка, а нечто иное.
← →
Юрий Федоров (2004-02-07 11:05) [10]>>jack128 © (06.02.04 21:38) [1]
>>для гарантии скопируй содержимое MyPCharVar
Это совершенно ни к чему, компилятор все сделает сам, скопирут (если нужно).Более того, поскольку там(при работе со string) идет подсчет ссылок, такая операция запросто может поставить компилятор в тупик - получим проблему.
автору ветки
Если ты возваращаешь значение из библиотеки, то лучше использовать widestring как тип параметра, а не pchar.
Потому что если длина возвращаемого значения больше, чем длина, быделенная по этот PChar отправителем запроса, явно прижется перевыделять память - значит PChar должен быть var параметром, а кто долден освобождать память ?
никакие ShareMem тут не пройдут по причине того, сто вызывает функцию приложение, написанное не на delphi.
А общее правило такое - кто выдедид память, тот ее и должен освобождать, кроме случаев хитрых манипуляций по передаче в DLL менеджера памяти
← →
nikkie (2004-02-07 16:00) [11]>Юрий Федоров
>то лучше использовать widestring как тип параметра, а не pchar.
в документации по OracleForms должно быть написано, можно ли это делать
>значит PChar должен быть var параметром, а кто долден освобождать память ?
вызывающий. как именно он это должен делать, должно быть написано в документации по OracleForms.
>А общее правило такое - кто выдедид память, тот ее и должен освобождать, кроме случаев хитрых манипуляций по передаче в DLL менеджера памяти
не надо передавать менеджер памяти. нужно просто документировать способ выделения и освобождения памяти. например, функция FormatMessage использует LocalAlloc - соответственно вызывающий должен использовать LocalFree, многие COM-компоненты используют CoTaskMemAlloc/CoTaskMemFree, ну и, понятное дело, работа с BSTR идет с помощью SysAllocString/SysFreeString.
← →
Genry (2004-02-07 16:16) [12]Спасибо всем кто откликнулся, но вот вариант
> jack128 © (06.02.04 21:38) [1]
не прошел.
Вернее если я вызываю из дельфи-приложения библиотеку, то она работает. А тот же OracleForms свалился (опять же без сообщений об ошибках) на строчке
SetLength(MyStringVar, StrLen(MyPCharVar));
← →
nikkie (2004-02-07 16:23) [13]спасибо тем, кто читает даже те ответы, в которых не приведен явный код.
← →
Genry (2004-02-07 16:29) [14]Объясню задачу подробнее.
Есть библиотека, которую я пишу. Подразумевается что ее будут вызывать любые приложения (не только написанные на Дельфи)
Одна из функций этой библиотеки должна выглядеть примерно так:
{Функция получает значение PChar, передает его в COM-объект, тот ее как-то меняет и в результате пользователь моей библиотеки должен получить измененное значение переменной. Результат функции - код ошибки}
function MyFunction(var MyPChar: PChar): Integer;
var MyStringVar
begin
.... // Тут мы должны скопировать полученный MyPChar в MyStringVar
Result:=MyOleAutObj.GetSomething(MyStringVar);
.... // Тут мы должны обратно скопировать MyStringVar в MyPChar
end;
Как это правильно реализовать - ума не приложу !
← →
nikkie (2004-02-07 16:49) [15]>Как это правильно реализовать - ума не приложу !
я уже 3 раза сказал - читать документацию по OracleForms.
ну и если приведешь код вызова функции и ее декларации в OracleForms - тоже может что-то прояснится.
← →
jack128 (2004-02-07 17:03) [16]
> Это совершенно ни к чему, компилятор все сделает сам, скопирут
> (если нужно).
Может быть, не проверял
>Более того, поскольку там(при работе со string)
> идет подсчет ссылок, такая операция запросто может поставить
> компилятор в тупик - получим проблему.
Это как приведенный выше код может поставить компилятор в тупик?
← →
Genry (2004-02-07 17:12) [17]
> nikkie © (07.02.04 16:49) [15]
> ну и если приведешь код вызова функции и ее декларации в
> OracleForms - тоже может что-то прояснится.
Не могу знать, т.к. тот кто вызывает мою библиотеку сидит в другой конторе. А у меня нету ни самого OracleForms ни описания к нему и чесно говоря я с ним ни разу не работал ...
Все что я знаю, так это то, что пользователь передает мне переменную string "по ссылке" как он выразился. При этом самостоятельно руками не выделяет под нее память (видимо это делает менеджер памяти OracleForms), а я получаю значение не равное nil.
← →
nikkie (2004-02-07 23:33) [18]>Не могу знать, т.к. тот кто вызывает мою библиотеку сидит в другой конторе.
1. существует e-mail
2. написать он мог что угодно - пусть пришлет свой код. заодно пусть пришлет кусок документации с прототипом функции. хотя бы на си.
3. ответственность за работу связки exe+dll лежит и на том, кто пишет dll, и на том, кто пишет exe. надо согласовать и прототип функции, и соглашение о вызове (stdcall/pascal).
← →
panov (2004-02-08 00:05) [19]>Genry (07.02.04 17:12) [17]
Все что я знаю, так это то, что пользователь передает мне переменную string "по ссылке"
1. Неважно, как ты будешь передавать и возвращать значение типа String.
В том и другом случае будет AV, если не используется ShareMem. А раз требуется использование функции в разных средах программирования, то ShareMem использовать нельзя. А следовательно, нельзя и передавать значение переменной, имеющий тип String.
2. Если планируется передача и обработка строк с длиной, не превышающей 255, то используй тип ShortString.
3. Если все же длинные строки будут использоваться, то в этом случае можно использовать 2 метода:
а) Определяется дополнительная функция, которая будет определяться в программе, предназначенная только для вызова твоей библиотечной функции. В эту дополнительную функцию как раз прередается значение строки, она же и возвращает стрококвое ззначение. Эта функция выделяет буфер достаточной длины для всех манипуляций со строками, копирует исходную строку в буфер и передает в библиотечную функцию 2 значения - указатель на начало буфера и длину данных в буфере.
Твоя библиотечная функция преобразует буфер в строку, делет с ней нужные манипуляции, копирует обратно в буфер выходную строку и возвращает длину данных, которую необходимо вернуть. Передать длину возвращаемых данных и дополнительно код ошибки можно разными способами(на это не будем внимание заострять).
Дополнительная функция получает длину данных, копирует ее в строку для возврата, освобождает память из под буфера. Всё.
б) Изменить способы передачи параметров.
Для этого клиент сам, без использования дополнительной функции должен придерживаться правил из п.а)
Но в этом сучае желательно придерживаться приемов, которые используются во многих функциях API.
1. Входной и выходной буфер различаются.
2. Функция должна САМА выделять буфер для возврата.
3. Функция должна передавать длину полезных данных
4. При вызове передаются:
- Адрес входных данных;
- Длина входных данных;
- Адрес буфера для возвращаемых данных;
- Адрес переменной, в которую будет возвращена длина
получаемых данных.
← →
Rouse_ (2004-02-08 00:18) [20]Саш, ну ты и намешал.... ;)
← →
nikkie (2004-02-08 00:19) [21]>panov
поскольку речь идет об вызове из OracleForms, то все рассуждения касательно дельфийского string здесь немного не в тему. надо знать, что имеется в виду под "string" в OracleForms.
← →
panov (2004-02-08 14:01) [22]>nikkie © (08.02.04 00:19) [21]
Думаю, что принцип будет все равно похож, а передается скорее всего varchar. Вот только автор не может найти описание.
А для проверки что-то лень ставить ORACLE себе...
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2004.02.17;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.01 c