Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

DLL [D6, WinXP]


Страницы:   1 2

Konsul ©   (2004-08-02 08:53:00) 

Здравствуйте, уважаемые мастера!
У меня возникла такая проблема, с которй сталкивается, наверное, каждый начинающий в области 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 - более глобальная переменна, значение которой задаётся какой-либо другой процедурой, то никаких ошибок нет. Странно!...
Мастера, помогите разобраться, в чём дело! Заранее благодарен!


Мастер   (2004-08-11 11:33:00) [1]

>Dizzy   (11.08.04 10:52) [20]
Поскольку Windows знать не знают ни про какой String, пользуйся PChar

Ошибочка.
Читай комментарии к Wizard DLL.


Dizzy   (2004-08-11 10:52:00) [2]

Konsul!

Когда пишешь DLL общее правило такое: нормально передаются и получаются без дополнительных ухищрений только типы известные системе. Поскольку Windows знать не знают ни про какой String, пользуйся PChar. Почитай Марко Канту (www.marcocantu.com), очень просто и грамотно описывает что такое хорошо и что такое плохо при программировании на Delphi.


sashok   (2004-08-07 21:51:00) [3]

Подключайте ShareMem в dll-ке и в программе и тогда можно использовать: string, strings.


Мастер   (2004-08-07 20:15:00) [4]

>GrayFace ©   (07.08.04 10:03) [17]

И при работе со String(AnsiString) и с PChar возникает 2 варианта:

1. В вызываемой функции изменяется размер строки.
2. В вызываемой функции не изменяется размер строки.

В первом варианте необходимо использовать ShareMem, либо собирать программу с опцией Build with Runtime packages, так как для перераспределения памяти будут использоваться разные менеджеры памяти, что приведет к непредсказуемым, разрушительным последствиям.

Вот втором случае можно совершенно спокойно обрабатывать переданные строки.
Но нужно учитывать(в случае передачи String(AnsiString)), что передача параметров происходит через стек, и передать можно не более 255 байт.


GrayFace   (2004-08-07 10:03:00) [5]

Slavka J. Borland   (06.08.04 6:07) [15]
> не пробовал, но по идее все должно работать, т.к. ты
> передаешь указатель, а не саму строку.

Наверняка при возврате строки тоже передается указатель, иначе такой проблемы не было бы. Вот только при присвоении строк Delphi увеличивает счетчик ссылок - наверное, AV возникает из-за этого.


-SeM-   (2004-08-06 12:04:00) [6]

Slavka J. Borland   (06.08.04 06:07) [15]

> то есть афигеный упаковщик, размер распаковщика которого
> сосбавляет 197 байт (!!!). F.S.G. назывется (F[ast] S[mall]
> G[ood])

Ссылочку можно?


Slavka J. Borland   (2004-08-06 06:07:00) [7]

>> Думкин ©   (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 в начале кажой программы.


GrayFace   (2004-08-05 14:23:00) [8]

А если возвратить PChar(IntToStr(i)), то все нормально будет?


Думкин   (2004-08-05 12:35:00) [9]

> [11] Slavka J. Borland   (05.08.04 12:22)

Есть стороннее - без ДЛЛ.


Slavka J. Borland   (2004-08-05 12:25:00) [10]

>> XShadow Dll не может возвращать String только PChar

Может! Еще как! Могу пояснить. Кому интересно: ICQ: 306684286


Slavka J. Borland   (2004-08-05 12:22:00) [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 делала, а они-то знают свое дело. Удачи в кодинге! :)


Digitman   (2004-08-05 10:37:00) [12]


> Юра   (05.08.04 10:23) [9]


тогда просто тебе для сведения : в случае сборки обоих проектов с ран-тайм пакетами эти проекты так же используют единый менеджер памяти


Юра   (2004-08-05 10:23:00) [13]

2Digitman
Не буду спорить. Давно на дельфях не программил. Во всяком случае, я постарался объяснить первопричину, а разобраться в опциях проекта, думаю, можно самому.


Digitman   (2004-08-05 10:15:00) [14]


> Юра   (05.08.04 09:49) [7]


> Build With Run-Time Packages тебе не поможет


еще как поможет
и уменьшение размера кода здесь ни при чем - это само собой разумеющееся


Юра   (2004-08-05 09:49:00) [15]

Правильно сказал Думкин.
Трабл заключается в том, что ДЛЛ использует свой менеджер памяти а exeшник свой. Выделение памяти под стринг происходит в длл, а удаление в ЕХЕ. Вот здесь и происходит нарушение доступа. Включи опцию и в ехе и в ДЛЛ Use dynamic RLT или работай с указателями на строку. Вообще правило такое: где создаешь ресурс там его и уничтожай. В СОМ для обхода такой стуации существует спец. интерфейс IMalloc, и еще много ухищрений, типа SysAllocString SysFreeString, SafeArrays и прочее.
Вообще есть хорошая штука, CodeGuard называется (в Билдере) Она в такие вещи сразу "носом тыкает" сообщением Resource from different RTL.

Build With Run-Time Packages тебе не поможет. Используй эту опцию для уменьшения размера кода. Но тогда ты должен поставлять все используемые проектом DLLки.


Digitman   (2004-08-05 09:18:00) [16]


> Konsul


собери оба проекта с опцией Build With Run-Time Packages


Konsul   (2004-08-05 09:15:00) [17]

> более глобальная переменна
Я имею ввиду, что объявленная на уровне всей dll.


Digitman   (2004-08-02 09:40:00) [18]


> более глобальная переменна


интересные, однако, нововведения)

оказывается "глобальность" переменной отныне можно оценивать на качественном уровне : "больше глобальности" или "меньше глобальности"


Рамиль   (2004-08-02 09:18:00) [19]


> Dll не может возвращать String только PChar

Может.


xShadow   (2004-08-02 09:00:00) [20]

Dll не может возвращать String только PChar


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо