Форум: "Начинающим";
Текущий архив: 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.048 c