![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Пресловутые PChar и DLL... [D2005, XP]
GL00m © (2007-04-12 19:38:00)Лазил в поиск, не нашел.
Задача: в длл есть функция которая получает 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 передается не тот адрес. В чем я не прав???
Johnmen (2007-04-13 18:52:00) [1]
> GL00m
Я был неправ. Беру свои слова обратно.
Дело в том, что компилятор интерпретирует data[0], data[1], ... как обращения к динамическому массиву, на первый элемент которого указывает data. А дин.массив, как известно, индексируется с 0.
GL00m (2007-04-13 18:13:00) [2]
> тут ты волен какой угодно calling convention юзать
Значит я правильно понимаю, что я тогда забиваю на все, удаляю из всех функций stdcall и работаю так, потому как кроме меня эту длл никто юзать не собирается?
clickmaker (2007-04-13 17:54:00) [3]
> Поясните, может здесь лучше использовать другое соглашение?
де-факто для ДЛЛ используют stdcall, чтобы не было разброда и шатания. Т.е. правилом хорошего тона будет то, что в созданной тобой ДЛЛ (если она потенциально будет кем-то использоваться) функции будут такими
Ну а если она "для дома, для семьи", то конечно тут ты волен какой угодно calling convention юзать
GL00m (2007-04-13 17:14:00) [4]
> А почему не добавлением stdcall в код хост-приложения ?
Про это я писал выше - получал AV.
> Почему вообще "stdcall" ? Почему не иное соглашение ? От
> балды что ли взято ?)
Как бы смешно это ни было, было взято действительно от балды, точнее, собиралось все по одной из статей про создание палгинов под делфи. Мне, честно говоря, эти соглашения вообще непонятны, кроме того, что:
по-умолчанию используется register и паскаль и си используют разный порядок передачи параметров. Толковой литературы я про это не нашел. Поясните, может здесь лучше использовать другое соглашение?
Сергей М. (2007-04-13 16:45:00) [5]
> проблема решилась простым убиранием stdcall из кода в длл
А почему не добавлением stdcall в код хост-приложения ?
Почему вообще "stdcall" ? Почему не иное соглашение ? От балды что ли взято ?)
GL00m (2007-04-13 15:56:00) [6]
> М-дя.... Если бы сказал "нулевой символ строки", то это
> хоть немного тебя извинило бы...
Первый по счету, а не по индексу. Честно говоря, сам удивился, когда заработало. Однако, учитывая сарказм в мою сторону, проверил: сделалStrPCopy(pd,'XYZ');, а потом в длле обратился не к нулевому, а к первому (по индексу =)) элементу и получил именно 'Y'. Так что, видимо не такой уж я и везунчик, видимо существует разница между работой со строкой и работой с указателем (оглядываясь на это, мне даже она кажется логичной).
> А и проблемы-то никакой нет - взял в зубы встроенный отладчик,
> да и прошелся им пошагово по своему коду).. авось и на
> мысль наведет)
Проблемы действительно нет, потому что я ее уже решил, а никто и не обратил внимания на разницу в передаче параметров. Код программы я излазил вдоль и поперек. А вот по коду скомпиленного длл-файла? Расскажите как. Этого я действительно не умею.
Сергей М. (2007-04-13 15:19:00) [7]
> GL00m (13.04.07 14:31) [15]
> Универсальный ответ на проблему,
А и проблемы-то никакой нет - взял в зубы встроенныйотладчик, да и прошелся им пошагово по своему коду).. авось и на мысль наведет)
Johnmen (2007-04-13 15:15:00) [8]
> Ну первый символ строки.
М-дя.... Если бы сказал "нулевой символ строки", то это хоть немного тебя извинило бы...
> В общем и целом - работает. =)
Это счастливая случайность. Видимо, ты везунчик...:)
GL00m (2007-04-13 15:07:00) [9]
> это, вообще-то, функции, которые возвращают результат. Неплохо
> бы им пользоваться.
Согласен, но факт, что и без него все работает. Но, опять же соглашусь, правильно использовать результат.
> Чёй-то за нуль??? :)
Ну первый символ строки. В общем и целом - работает. =)
Johnmen (2007-04-13 14:44:00) [10]
> if data[0] = 'Y' then
Чёй-то за нуль??? :)
umbra (2007-04-13 14:37:00) [11]
> StrPCopy(pd,'YYY');
> StrLCopy(data,'XXX',5);
это, вообще-то, функции, которые возвращают результат. Неплохо бы им пользоваться.
> Универсальный ответ на проблему,
так оно и есть
GL00m (2007-04-13 14:35:00) [12]Да, а проблема решилась простым убиранием stdcall из кода в длл:
вместо function GetData(data:PChar):Integer;stdcall;
надо было function GetData(data:PChar):Integer;
GL00m (2007-04-13 14:31:00) [13]
> Ты слова "отладка", "отладчик" слышал ?
>
> Они тебе хоть о чем-либо говорят ?
Универсальный ответ на проблему, по которой сказать нечего, а сказать что-нибудь хочется. Я пишу в форум для начинающих и считаю свой вопрос корректно поставленным. Если не знаешь ответа на вопрос, то в крайнем случае можно ограничиться обычным "не знаю".
Сергей М. (2007-04-13 13:52:00) [14]
> GL00m (13.04.07 13:48) [13]
Ты слова "отладка", "отладчик" слышал ?
Они тебе хоть о чем-либо говорят ?
GL00m (2007-04-13 13:48:00) [15]В общем изменение вызова функции:
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'.
Ega23 (2007-04-13 13:44:00) [16]
> Because AnsiStrings (long strings) are implicitly null terminated
> and dynamically allocated, the use of StrAlloc is deprecated.
А это для PChar
GL00m (2007-04-13 13:29:00) [17]
> 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:18:00) [18]StrAlloc, StrPCopy, StrDispose + F1
GL00m (2007-04-13 13:16:00) [19]Да, значение pd я проверяю, конечно же, до ФриМема.
GL00m (2007-04-13 13:14:00) [20]
> Думаешь теперь имеешь три байта памяти с которыми можешь
> делать что хочешь? Ошибаешься.
> Выдели явным образом нужный буфер памяти, а затем уж используй.
>
Может я и не прав. Изменил вызов функции на:
GetMem(pd,255);
R := Plugins.DllGetData(pd);
FreeMem(pd,255);
Ничего не изменилось.