Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.02.17;
Скачать: CL | DM;

Вниз

Как правильно присвоить 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;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.016 c
1-53609
Бомбома
2004-02-07 12:45
2004.02.17
arccos


1-53487
Вованчик
2004-02-06 08:00
2004.02.17
Как исключить Qtintf70.dll из дистрибутива?


1-53557
WebErr
2004-02-09 15:23
2004.02.17
Функция CreateProcess в Delphi


3-53363
Andriy Tysh
2004-01-28 11:11
2004.02.17
stack overloor in DBGridEh.Notification при создании формы


1-53583
VID
2004-02-07 14:00
2004.02.17
Глюк у RichEdit