Текущий архив: 2004.08.29;
Скачать: CL | DM;
Вниз
DLL Найти похожие ветки
← →
Konsul (2004-08-02 08:53) [0]Здравствуйте, уважаемые мастера!
У меня возникла такая проблема, с которй сталкивается, наверное, каждый начинающий в области dll.
Проблема вот в чём. Задаю в dll функцию, возвращающую значение string. Сама программа работает с dll следующим образом:
задаём переменные:type TGetStr=function: string; stdcall;
var
Hinst: THandle;
FPointer: TFarProc;
GetStr: TGetStr;
s: string;
Затем выполняем слeдующие действия:HInst:=LoadLibrary(PChar("test_dll.dll"));
if HInst<=0 then begin messagedlg("DLL глючит!",mtError,[mbOk],0); exit; end;
FPointer:=GetProcAddress(Hinst,PChar("GetStr"));
if FPointer<>nil then
begin
GetStr:=TGetStr(FPointer);
s:=GetStr;
end;
если в самой dll возвращяемое значение задать прямым значением или переменой, относящейся к данной функции, т.е.function GetStr: string; stdcall;
begin
result:="Test string!";
end;
то прога получает это значение, но потом пишет ошибку EInvalidPointer with message "Invalid Pointer operation". Но если задать result так:
function GetStr: string; stdcall;
begin
result:=s;
end;
где s - более глобальная переменна, значение которой задаётся какой-либо другой процедурой, то никаких ошибок нет. Странно!...
Мастера, помогите разобраться, в чём дело! Заранее благодарен!
← →
xShadow © (2004-08-02 09:00) [1]Dll не может возвращать String только PChar
← →
Думкин © (2004-08-02 09:00) [2]А ты пробовал читать комментарий вверху dll, когда был создан ее юнит. Он не только для красоты.
← →
Рамиль © (2004-08-02 09:18) [3]
> Dll не может возвращать String только PChar
Может.
← →
Digitman © (2004-08-02 09:40) [4]
> более глобальная переменна
интересные, однако, нововведения)
оказывается "глобальность" переменной отныне можно оценивать на качественном уровне : "больше глобальности" или "меньше глобальности"
← →
Konsul (2004-08-05 09:15) [5]> более глобальная переменна
Я имею ввиду, что объявленная на уровне всей dll.
← →
Digitman © (2004-08-05 09:18) [6]
> Konsul
собери оба проекта с опцией Build With Run-Time Packages
← →
Юра (2004-08-05 09:49) [7]Правильно сказал Думкин.
Трабл заключается в том, что ДЛЛ использует свой менеджер памяти а exeшник свой. Выделение памяти под стринг происходит в длл, а удаление в ЕХЕ. Вот здесь и происходит нарушение доступа. Включи опцию и в ехе и в ДЛЛ Use dynamic RLT или работай с указателями на строку. Вообще правило такое: где создаешь ресурс там его и уничтожай. В СОМ для обхода такой стуации существует спец. интерфейс IMalloc, и еще много ухищрений, типа SysAllocString SysFreeString, SafeArrays и прочее.
Вообще есть хорошая штука, CodeGuard называется (в Билдере) Она в такие вещи сразу "носом тыкает" сообщением Resource from different RTL.
Build With Run-Time Packages тебе не поможет. Используй эту опцию для уменьшения размера кода. Но тогда ты должен поставлять все используемые проектом DLLки.
← →
Digitman © (2004-08-05 10:15) [8]
> Юра (05.08.04 09:49) [7]
> Build With Run-Time Packages тебе не поможет
еще как поможет
и уменьшение размера кода здесь ни при чем - это само собой разумеющееся
← →
Юра (2004-08-05 10:23) [9]2Digitman
Не буду спорить. Давно на дельфях не программил. Во всяком случае, я постарался объяснить первопричину, а разобраться в опциях проекта, думаю, можно самому.
← →
Digitman © (2004-08-05 10:37) [10]
> Юра (05.08.04 10:23) [9]
тогда просто тебе для сведения : в случае сборки обоих проектов с ран-тайм пакетами эти проекты так же используют единый менеджер памяти
← →
Slavka J. Borland (2004-08-05 12:22) [11]Есть такая замечателдьная везчь. Называется ShareMem.pas. Его пишешь ПЕРВЫМ модулем в библиотеки и программе. Не в PAS юните, а в DPR. Т.е. у тебя DPR примерно так выгдядит:
program ASMaker;
uses
ShareMem, // - ОБЯЗАТЕЛЬНО ПЕРВЫМ СТАВЬ!
Forms,
SplashUnit in "SplashUnit.pas" {SplashForm},
WizardUnit in "WizardUnit.pas" {WizardForm},
ComponentUnit in "ComponentUnit.pas" {CompForm};
. . . . . .
Также в библиотеке. Тока тебе придется таскать с собой библиотеку brlndmm.dll (около 20 килов). Это юнит (ShareMem) станжартный. Т.е. есть уже в Delphi. Ставь, компилируй. Живи и радуйся. А вообще без него можно передавать строки типа ShortString, PChar, PAnsiString и т.д. Но вообще я сам SgareMem юзаю. Чего и вам желаю. В инете есть много юнитов, которые без DLL тебе могут заменить это все, но тут все же Borland делала, а они-то знают свое дело. Удачи в кодинге! :)
← →
Slavka J. Borland (2004-08-05 12:25) [12]>> XShadow Dll не может возвращать String только PChar
Может! Еще как! Могу пояснить. Кому интересно: ICQ: 306684286
← →
Думкин © (2004-08-05 12:35) [13]> [11] Slavka J. Borland (05.08.04 12:22)
Есть стороннее - без ДЛЛ.
← →
GrayFace © (2004-08-05 14:23) [14]А если возвратить PChar(IntToStr(i)), то все нормально будет?
← →
Slavka J. Borland (2004-08-06 06:07) [15]>> Думкин © (05.08.04 12:35) [13]
Знаю, есть. У меня даже есть, даже могу дать. Сам модуль состоит из одного класса и его просто в uses надо прописать. Размер около 4 килобайт. Пишите, могу скинуть.
>> GrayFace © (05.08.04 14:23) [14]
Хм. . . .. не пробовал, но по идее все должно работать, т.к. ты передаешь указатель, а не саму строку. А вообще, еще раз говорю, мне легче не мучаться, а прикрепить к своему проекту файлик brlndmm.dll (BoRLaND Memory Manager) размер в 30 килобайт и ShareMem в uses. Да потом, при желании, саму эту DLL можно пожать UPX"ом, а если хреново пожмется, то есть афигеный упаковщик, размер распаковщика которого сосбавляет 197 байт (!!!). F.S.G. назывется (F[ast] S[mall] G[ood]). Я им жму свои программы на MASM"е. Ента штукенция пожала прогу в 2,5 килобайта до 750 байт. Но я отвлекся от темы и потом все это на любителя. На вкус и цвет товарищей нет. Еще раз говорю, что я предпочитаю таскать с собой Борладновскую DLL и ShareMem в начале кажой программы.
← →
-SeM- (2004-08-06 12:04) [16]Slavka J. Borland (06.08.04 06:07) [15]
> то есть афигеный упаковщик, размер распаковщика которого
> сосбавляет 197 байт (!!!). F.S.G. назывется (F[ast] S[mall]
> G[ood])
Ссылочку можно?
← →
GrayFace © (2004-08-07 10:03) [17]Slavka J. Borland (06.08.04 6:07) [15]
> не пробовал, но по идее все должно работать, т.к. ты
> передаешь указатель, а не саму строку.
Наверняка при возврате строки тоже передается указатель, иначе такой проблемы не было бы. Вот только при присвоении строк Delphi увеличивает счетчик ссылок - наверное, AV возникает из-за этого.
← →
Мастер © (2004-08-07 20:15) [18]>GrayFace © (07.08.04 10:03) [17]
И при работе со String(AnsiString) и с PChar возникает 2 варианта:
1. В вызываемой функции изменяется размер строки.
2. В вызываемой функции не изменяется размер строки.
В первом варианте необходимо использовать ShareMem, либо собирать программу с опцией Build with Runtime packages, так как для перераспределения памяти будут использоваться разные менеджеры памяти, что приведет к непредсказуемым, разрушительным последствиям.
Вот втором случае можно совершенно спокойно обрабатывать переданные строки.
Но нужно учитывать(в случае передачи String(AnsiString)), что передача параметров происходит через стек, и передать можно не более 255 байт.
← →
sashok (2004-08-07 21:51) [19]Подключайте ShareMem в dll-ке и в программе и тогда можно использовать: string, strings.
← →
Dizzy (2004-08-11 10:52) [20]Konsul!
Когда пишешь DLL общее правило такое: нормально передаются и получаются без дополнительных ухищрений только типы известные системе. Поскольку Windows знать не знают ни про какой String, пользуйся PChar. Почитай Марко Канту (www.marcocantu.com), очень просто и грамотно описывает что такое хорошо и что такое плохо при программировании на Delphi.
← →
Мастер © (2004-08-11 11:33) [21]>Dizzy (11.08.04 10:52) [20]
Поскольку Windows знать не знают ни про какой String, пользуйся PChar
Ошибочка.
Читай комментарии к Wizard DLL.
Страницы: 1 вся ветка
Текущий архив: 2004.08.29;
Скачать: CL | DM;
Память: 0.5 MB
Время: 0.095 c