Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2007.05.06;
Скачать: [xml.tar.bz2];

Вниз

Пресловутые PChar и DLL...   Найти похожие ветки 

 
GL00m   (2007-04-12 19:38) [0]

Лазил в поиск, не нашел.
Задача: в длл есть функция которая получает PChar, записывает в него данные и возвращает обратно вместе с результатом работы (Integer).
Код в длл:

function GetData(data:PChar):Integer;stdcall;
begin
 StrLCopy(data,"XXX",5);
 Result := 1;
end;
...
exports
 GetData index 1 name "GetData";
begin
end.

Код в программе:

type
 TMyGetData = function(data:PChar):integer;
 ...
 CPlugins = class
 ...
 function DllGetData(data:PChar):Integer;

implementation
function CPlugins.DllGetData(data:PChar): Integer;
var
 h : Integer;
 f : TMyGetData;
begin
 Result := 0;
 h := LoadLibrary(PChar(DllFile));
 @f := GetProcAddress(h,"GetData");
 Result := f(data);
 FreeLibrary(h);
end;

Ну и потом вызов:

d : String;
pd : PChar;
R : Integer;

d := "yyy";
pd := PChar(d);
R := Plugins.DllGetData(pd);

Ожидается, что в итоге в pd будет "XXX". Ан нет, там все тот же "yyy", хотя в R содержится любое число, которое я задам в длл-ке.
На момент передачи data в функцию f, ее адрес равен адресу pd, но при попытке вывести содержимого data из dll, получаю бред, т.е. единственный вывод, который я смог сделать, что в dll передается не тот адрес. В чем я не прав???


 
umbra ©   (2007-04-12 19:54) [1]

а какую длину имеет строка d перед приведением ее к PChar? Т.е. на область памяти какого размера указывает pd?


 
trubin ©   (2007-04-12 20:01) [2]


> function GetData(data:PChar):Integer;stdcall;

function GetData(var data:PChar):Integer;stdcall;


 
umbra ©   (2007-04-12 20:01) [3]

так это вообще фрипаскаль :)
http://www.freepascal.org/docs-html/rtl/sysutils/strlcopy.html


 
trubin ©   (2007-04-12 20:31) [4]


> type
>  TMyGetData = function(data:PChar):integer;


TMyGetData = function(data:PChar):integer;stdcall;


 
Loginov Dmitry ©   (2007-04-13 08:07) [5]

Все-равно AV словит (должен словить, если все правильно сделает)


 
GL00m   (2007-04-13 11:40) [6]


> а какую длину имеет строка d перед приведением ее к PChar?
>  Т.е. на область памяти какого размера указывает pd?

d := "yyy";
pd := PChar(d);

По-моему оно?

> function GetData(var data:PChar):Integer;stdcall;

Насколько я понимаю, вар перед переменной ставится для того, чтобы измененное значение переменной в функции вернулось наружу, но в данном случае я передаю указатель и его-то менять не надо, а надо изменить содержимое памяти по этому указателю. (честно говоря, пробовал еще вчера этот вариант - то же самое)

> так это вообще фрипаскаль :)

Извините, не понял, к чему это...

> TMyGetData = function(data:PChar):integer;stdcall;

Действительно, получаю аксес вайолэйшин.

> Все-равно AV словит (должен словить, если все правильно
> сделает)

А что мне делать? Мне нужно просто из функции в длл-ке получить строку и целое. А выходит так, что целое я получаю нормально, а ПЧар, который я туда передаю, в функцию уже приходит не тот, что был изначально, соответственно, на выходе ничего не меняется...


 
ЮЮ ©   (2007-04-13 11:54) [7]

d := "yyy";

Думаешь теперь имеешь три байта памяти с которыми можешь делать что хочешь? Ошибаешься.
Выдели явным образом нужный буфер памяти, а затем уж используй.


 
GL00m   (2007-04-13 13:14) [8]


> Думаешь теперь имеешь три байта памяти с которыми можешь
> делать что хочешь? Ошибаешься.
> Выдели явным образом нужный буфер памяти, а затем уж используй.
>

Может я и не прав. Изменил вызов функции на:
 GetMem(pd,255);
 R := Plugins.DllGetData(pd);
 FreeMem(pd,255);

Ничего не изменилось.


 
GL00m   (2007-04-13 13:16) [9]

Да, значение pd я проверяю, конечно же, до ФриМема.


 
Ega23 ©   (2007-04-13 13:18) [10]

StrAlloc, StrPCopy, StrDispose + F1


 
GL00m   (2007-04-13 13:29) [11]


> StrAlloc, StrPCopy, StrDispose + F1

Сейчас проверю, но Ф1 дает:
Because AnsiStrings (long strings) are implicitly null terminated and dynamically allocated, the use of StrAlloc is deprecated.


 
Ega23 ©   (2007-04-13 13:44) [12]


> Because AnsiStrings (long strings) are implicitly null terminated
> and dynamically allocated, the use of StrAlloc is deprecated.


А это для PChar


 
GL00m   (2007-04-13 13:48) [13]

В общем изменение вызова функции:
 pd := StrAlloc(255);
 pd := StrPCopy(pd,"YYY");
 R := Plugins.DllGetData(pd);
 StrDispose(pd);

Изменение функции в длл:
 if data[0] = "Y" then Result := 0
 else result := 1;
 StrPCopy(data,"XXX");

Ничего не меняет: R = 1, pd = "YYY".


 
Сергей М. ©   (2007-04-13 13:52) [14]


> GL00m   (13.04.07 13:48) [13]


Ты слова "отладка", "отладчик" слышал ?

Они тебе хоть о чем-либо говорят ?


 
GL00m   (2007-04-13 14:31) [15]


> Ты слова "отладка", "отладчик" слышал ?
>
> Они тебе хоть о чем-либо говорят ?

Универсальный ответ на проблему, по которой сказать нечего, а сказать что-нибудь хочется. Я пишу в форум для начинающих и считаю свой вопрос корректно поставленным. Если не знаешь ответа на вопрос, то в крайнем случае можно ограничиться обычным "не знаю".


 
GL00m   (2007-04-13 14:35) [16]

Да, а проблема решилась простым убиранием stdcall из кода в длл:
вместо function GetData(data:PChar):Integer;stdcall;
надо было function GetData(data:PChar):Integer;


 
umbra ©   (2007-04-13 14:37) [17]


>   StrPCopy(pd,"YYY");


>  StrLCopy(data,"XXX",5);

это, вообще-то, функции, которые возвращают результат. Неплохо бы им пользоваться.


> Универсальный ответ на проблему,

так оно и есть


 
Johnmen ©   (2007-04-13 14:44) [18]


> if data[0] = "Y" then

Чёй-то за нуль??? :)


 
GL00m   (2007-04-13 15:07) [19]


> это, вообще-то, функции, которые возвращают результат. Неплохо
> бы им пользоваться.

Согласен, но факт, что и без него все работает. Но, опять же соглашусь, правильно использовать результат.

> Чёй-то за нуль??? :)

Ну первый символ строки. В общем и целом - работает. =)


 
Johnmen ©   (2007-04-13 15:15) [20]


> Ну первый символ строки.

М-дя.... Если бы сказал "нулевой символ строки", то это хоть немного тебя извинило бы...

>  В общем и целом - работает. =)

Это счастливая случайность. Видимо, ты везунчик...:)


 
Сергей М. ©   (2007-04-13 15:19) [21]


> GL00m   (13.04.07 14:31) [15]
> Универсальный ответ на проблему,


А и проблемы-то никакой нет - взял в зубы встроенный отладчик, да и прошелся им пошагово по своему коду).. авось и на мысль наведет)


 
GL00m   (2007-04-13 15:56) [22]


> М-дя.... Если бы сказал "нулевой символ строки", то это
> хоть немного тебя извинило бы...

Первый по счету, а не по индексу. Честно говоря, сам удивился, когда заработало. Однако, учитывая сарказм в мою сторону, проверил: сделал StrPCopy(pd,"XYZ");, а потом в длле обратился не к нулевому, а к первому (по индексу =)) элементу и получил именно "Y". Так что, видимо не такой уж я и везунчик, видимо существует разница между работой со строкой и работой с указателем (оглядываясь на это, мне даже она кажется логичной).

> А и проблемы-то никакой нет - взял в зубы встроенный отладчик,
>  да и прошелся им пошагово по своему коду).. авось и на
> мысль наведет)

Проблемы действительно нет, потому что я ее уже решил, а никто и не обратил внимания на разницу в передаче параметров. Код программы я излазил вдоль и поперек. А вот по коду скомпиленного длл-файла? Расскажите как. Этого я действительно не умею.


 
Сергей М. ©   (2007-04-13 16:45) [23]


> проблема решилась простым убиранием stdcall из кода в длл


А почему не добавлением stdcall в код хост-приложения ?

Почему вообще "stdcall" ? Почему не иное соглашение ? От балды что ли взято ?)


 
GL00m   (2007-04-13 17:14) [24]


> А почему не добавлением stdcall в код хост-приложения ?

Про это я писал выше - получал AV.
> Почему вообще "stdcall" ? Почему не иное соглашение ? От
> балды что ли взято ?)

Как бы смешно это ни было, было взято действительно от балды, точнее, собиралось все по одной из статей про создание палгинов под делфи. Мне, честно говоря, эти соглашения вообще непонятны, кроме того, что:
по-умолчанию используется register и паскаль и си используют разный порядок передачи параметров. Толковой литературы я про это не нашел. Поясните, может здесь лучше использовать другое соглашение?


 
clickmaker ©   (2007-04-13 17:54) [25]


> Поясните, может здесь лучше использовать другое соглашение?

де-факто для ДЛЛ используют stdcall, чтобы не было разброда и шатания. Т.е. правилом хорошего тона будет то, что в созданной тобой ДЛЛ (если она потенциально будет кем-то использоваться) функции будут такими
Ну а если она "для дома, для семьи", то конечно тут ты волен какой угодно calling convention юзать


 
GL00m   (2007-04-13 18:13) [26]


> тут ты волен какой угодно calling convention юзать

Значит я правильно понимаю, что я тогда забиваю на все, удаляю из всех функций stdcall и работаю так, потому как кроме меня эту длл никто юзать не собирается?


 
Johnmen ©   (2007-04-13 18:52) [27]


> GL00m

Я был неправ. Беру свои слова обратно.
Дело в том, что компилятор интерпретирует data[0], data[1], ... как обращения к динамическому массиву, на первый элемент которого указывает data. А дин.массив, как известно, индексируется с 0.



Страницы: 1 вся ветка

Форум: "Начинающим";
Текущий архив: 2007.05.06;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.52 MB
Время: 0.115 c
3-1171441590
Монг
2007-02-14 11:26
2007.05.06
Компонет cxGrid


15-1175902656
SerJaNT
2007-04-07 03:37
2007.05.06
Просьба администраторам


2-1176817310
Gentos
2007-04-17 17:41
2007.05.06
DBImage1: TDBImage; - с какой компонентой проще всего работать ?


8-1156315403
Maxim new
2006-08-23 10:43
2007.05.06
Ассоциация файлов


1-1173269911
ElectriC
2007-03-07 15:18
2007.05.06
Обработка ошибок(Исключений)





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский