Работа с фун. из Dll
У меня такой вопрос:
Есть на свете такая штуковина как DLL. Ну мне тоже такую захотелось (потому что действительно нужно). Так вот, будем считать, что в DLL'ке описана одна функция:
begin
Result:=X+Y;
end;
exports Summ;
Теперь мне надо вызвать ее в программе, и это делается так:
function Summ(X,Y:Integer):Integer; StdCall;
.....
implementanion
function summ; external 'my.dll';
.....
Так работает.
Проблемы начинаются, когда мне надо эту самую функцию из DLL, заставить быть методом моего класса!
пишу, дескать мол:
function Summ(X,Y:Integer):Integer; StdCall;
end;
.......
implementation
function summ; external 'my.dll';
.......
и... delphi посылает меня куда-то далеко, при этом выкрикивая ошибку: [Error]: Function needs result type (вроде как не описан тип самой функции, но я же знаю, что это вранье.
Помучившись, начитавшись хелпа и ничего там не найдя, я решил попробовать написать так:
implementation
function MyClass.summ; external 'my.dll';
.......
все скомпилировалось,НО, при запуске программы написалось, что в my.dll нет такой функции!
Что делать-то? Мне надо по-любому затолкать Summ в методы MyClass!
Коллеги, друзья, соратники, программисты! Помогите, пожалуйста!
У меня такой вопрос:
Есть на свете такая штуковина как DLL. Ну мне тоже такую захотелось (потому что действительно нужно). Так вот, будем считать, что в DLL'ке описана одна функция:
begin
Result:=X+Y;
end;
exports Summ;
Теперь мне надо вызвать ее в программе, и это делается так:
function Summ(X,Y:Integer):Integer; StdCall;
.....
implementanion
function summ; external 'my.dll';
.....
Так работает.
Проблемы начинаются, когда мне надо эту самую функцию из DLL, заставить быть методом моего класса!
пишу, дескать мол:
function Summ(X,Y:Integer):Integer; StdCall;
end;
.......
implementation
function summ; external 'my.dll';
.......
и... delphi посылает меня куда-то далеко, при этом выкрикивая ошибку: [Error]: Function needs result type (вроде как не описан тип самой функции, но я же знаю, что это вранье.
Помучившись, начитавшись хелпа и ничего там не найдя, я решил попробовать написать так:
implementation
function MyClass.summ; external 'my.dll';
.......
все скомпилировалось,НО, при запуске программы написалось, что в my.dll нет такой функции!
Что делать-то? Мне надо по-любому затолкать Summ в методы MyClass!
Такое сделать невозможно. Единственное решение - когда метод является "оберткой" вызова функции из DLL.
interface
type
TMyClass = class
function Summ(X, Y: Integer): Integer;
end;
...
function DllSumm(X, Y: Integer): Integer; StdCall;
...
implementation
function DllSumm; external 'my.dll';
...
function TMyClass.Summ(X, Y: Integer): Integer;
begin
Result := DllSumm(X, Y);
end;
Вызывай dll-функцию из функции класса
К такому решению я уже пришел.
А у меня теперь еще один вопрос:
В dll'ке прописана функция возвращающая строку,пусть так:
begin
result:=IntToStr(x);
end;
exports AB;
Но когда я вызываю ее на выполнение в программе, то пишется ошибка, вроде как или переполнение стека идет, или еще что-то (нет щас под рукой программы). Я где-то слышал, что не стоит работать c dll с типом данных string, а лучше использовать PChar. Если кто знает, что и почему, то ответьте пожалуйста
Я где-то слышал, что не стоит работать c dll с типом данных string, а лучше использовать PChar.
Всё верно...
begin
p:= PChar(IntToStr(x));
end;
exports AB;
точно не знаю... нужен var или нет.... пищу без delphi...
А почему все верно?По какой причине нельзя передавать строки в dll и из него?
А почему все верно?По какой причине нельзя передавать строки в dll и из него?
Marco Cantu: "... более правильно воспользоваться только собственными типами данных Windows... В целях совместимости следует избегать применения следующих типов Delphi: объектов, с которыми другие языки в принципе не могут работать, и строк Pascal, которые можно заменить строками типа PChar... вы не сможете передавать в DLL строки Delphi без некоторых предворительных преобразований. Это связано со способом управления строками в Delphi: автоматическим размещением, перемещением и освобождением их в памяти..."
...
function AB(X: Integer; P: PChar; PSize: Cardinal): LongBool;
var
S: String;
begin
S := IntToStr(x);
if psize > Length(S) + 1 then begin
StrPCopy(P, S);
StrCat(P, #0)
Result := True;
end else Result := False
end;
...
exports AB;
...
(А пробовал я сделать следующее: в DLL писал:
TMyClass = class
function MyFun(x:integer):integer; stdcall;
end;
function TMyClass.MyFun(x:integer):integer;
begin
result:=x;
end;
exports TMyClass.MyFun; //Вот здесь-то и возникает ошибка
вроде как пытаюсь экспортировать функцию, в которой используется местный формат.
[QUOTE]Originally posted by verybadbug
А почему все верно?По какой причине нельзя передавать строки в dll и из него?
А вот и неверно :) Работать со строками можно!
Итак, создаем проект DLL. В автоматически созданном файле DLL присетствует следующий комментарий:
Important note about DLL memory management: ShareMem must be the
first unit in your library's USES clause AND your project's (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters.
Перевод:
Важное замечание по управлению памятью в DLL: если DLL экспортирует процедуры или функции, которые принимают строки как параметры, или возвращают их в качестве результата, то необходимо поместить в секцию uses проекта DLL и проекта, использующего эту DLL модуль ShareMem и это объявление должно быть первым. Это условие применимо ко всем строковым параметрам, доже к тем, которые вложены в запись (record) или объявляются внутри класса, которые передаются в DLL. ShareMem - интерфейсный модуль к библиотеке BORLANDMM.DLL, которая является общим менеджером памяти и должна распространяться вместе с вашей DLL. Для того, чтобы избежать использование BORLANDMM.DLL, используйте в качестве параметров вместо строк (string) типы PChar или ShortString.
Таким образом, если пользуешься типом string, придется таскать вместе с проектом borlandmm.dll ;)
Таким образом, если пользуешься типом string, придется таскать вместе с проектом borlandmm.dll ;)
Это лишний геморрой P( ....
На мой взгляд лучше Виндовские типы использовать... Вобщем каждому своё! :}
Это лишний геморрой P( ....
На мой взгляд лучше Виндовские типы использовать... Вобщем каждому своё! :}
Дык блин, я и не спорю... просто возможность всетаки есть и о ней надо знать :)
Хотел как лучше, получилось....
ХА! если у тебя массив - это массив строк, то я тебе не завидую. И если ты каждую строку конвертишь из string в PChar а в библиотеке - наоборот, то ясен пенть бессмысленное символогоняние будет сильно затормаживать вычисления.
Как вариант - можно использовать пакеты, тогда borlndmm.dll не нужна и все можно передавать "как есть".
ХА! если у тебя массив - это массив строк, то я тебе не завидую. И если ты каждую строку конвертишь из string в PChar а в библиотеке - наоборот, то ясен пенть бессмысленное символогоняние будет сильно затормаживать вычисления.
Как вариант - можно использовать пакеты, тогда borlndmm.dll не нужна и все можно передавать "как есть".
Ну, да, приходится делать что-то подобное, правда я конвертирую string в PChar и наоборот всего по одному разу за все время исполнения кода. Так что из-за этого не должны лаги появлятся!!! Тут фишка в чем-то другом зарыта, может динамические массивы тоже тормозят вычисления как хрен знает что?
А вот про пакетики можно поподробнее, уж больно мне не охота отказываться от такой козырной штуки, как DLL. Да и вообще уже давно хочется узнать что это такое, да вот все руки не доходили! Заранее благодарю!
Я так понял...
Ты действительно не знаешь элементарного синтаксиса Object Pascal или прикалываешься? :D :D
packed - это резервированное слово для "упаковки" рекордов и массивов (подробнее - RTFM), и отношения к DLL аПсолютно не имеет.
В отношении твоей программы, думаю будет удобнее использовать string в библиотеках в явном виде и пихнуть рядом с приложением библиотеку borlndmm.dll
Пакеты - это *.bpl файлы (фактически тоже библиотеки dll) которые загружаются вместе с исполняемым файлом, и в отличие от обычных dll составляют единое адресное пространство и имеют единый менеджер памяти с экзешником.
Ты действительно не знаешь элементарного синтаксиса Object Pascal или прикалываешься? :D :D
packed - это резервированное слово для "упаковки" рекордов и массивов (подробнее - RTFM), и отношения к DLL аПсолютно не имеет.
В отношении твоей программы, думаю будет удобнее использовать string в библиотеках в явном виде и пихнуть рядом с приложением библиотеку borlndmm.dll
Пакеты - это *.bpl файлы (фактически тоже библиотеки dll) которые загружаются вместе с исполняемым файлом, и в отличие от обычных dll составляют единое адресное пространство и имеют единый менеджер памяти с экзешником.
Я приколы ловлю в других местах! А так я действительно не знал, что за пакеты имелись ввиду. Но постепенно просвещаюсь. А вот слово packed я нигде кроме как при просмотре подключаемых к unit'у модулей не встречал (но там ведь не написано что, как и зачем, ну только если по-ихнему - по-буржуйски). Я понимаю, что вы считаете, что я либо вечно укуренный чувак, либо человек, который печатает не то что думает (типа я так, - зашел просто потрещать), но нет - я действительно еще очень многого не знаю, потому что берусь за изучение чего-то нового в 3-ёх случаях:
1.Появляется задача, где старыми известными мне методами мне не обойтись, либо очень долго
2.Есть свободное время (это очень редко встречается)
3.Попадается интересная статья или тема на форуме (этот пункт практически полностью зависит от п.2)
Так вот, продолжу. Я сказал, что еще дохрена чё не знаю, например, что за словечки такие ABSTRACT и VIRTUAL. Вычитал где-то, что при их помощи можно экспортировать классы из DLL. Не мог бы кто-нибудь меня просветить, шо да как. (Если несложно то про packed тоже (каким образом это работает и т.д.)
Я сказал, что еще дохрена чё не знаю, например, что за словечки такие ABSTRACT и VIRTUAL. Вычитал где-то, что при их помощи можно экспортировать классы из DLL. Не мог бы кто-нибудь меня просветить, шо да как.
Тебе повезло - я сегодня выспавшийся и обедал. а значит добрый. Смотри проект - там пример создания абстрактного класса и его экспорт из ДЛЛ, а также то же самое, но используя интерфейс.
Про слово packed: в настройках компилятора есть такое свойство, как выравнивание полей классов/записей по байтам (обычно 4 или 8 байтов). если у нас поле занимает 1 байт, то оно будет занимать в памяти эти самые 4 байта. принаписании packed в объявлении записи выравниевание происходит по краям полей и наше поле займёт положенный 1 байт, а не 4. С массивами - аналогично, но, по-моему, для массивов packed включено всегда уже в компиляторе.
Тебе повезло - я сегодня выспавшийся и обедал. а значит добрый.
Да ты очень хорошо выспался и пообедал!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Очень признателен за столь ценный и информативный подарочек! Буду его хранить до следующего форматирования точно!