Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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
1-53455
Dik
2004-02-06 15:51
2004.02.17
TRichEdit


14-53771
Kerk
2004-01-27 14:25
2004.02.17
Merak Mail Server


1-53450
lokid7
2004-02-06 17:11
2004.02.17
Взаимодействие между двумя классами


1-53472
xz-man
2004-02-06 04:06
2004.02.17
Mdi-forms


1-53484
zamkom
2004-02-05 17:29
2004.02.17
Формат даты





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский