Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Работа с фун. из Dll

6.9K
09 апреля 2006 года
Britney
69 / / 20.03.2006
Коллеги, друзья, соратники, программисты! Помогите, пожалуйста!
У меня такой вопрос:
Есть на свете такая штуковина как DLL. Ну мне тоже такую захотелось (потому что действительно нужно). Так вот, будем считать, что в DLL'ке описана одна функция:
 
Код:
function Summ(X,Y:Integer):Integer; StdCall;
begin
  Result:=X+Y;
end;

exports Summ;


Теперь мне надо вызвать ее в программе, и это делается так:
 
Код:
.....
function Summ(X,Y:Integer):Integer; StdCall;
.....
implementanion
function summ; external 'my.dll';
.....

Так работает.

Проблемы начинаются, когда мне надо эту самую функцию из DLL, заставить быть методом моего класса!
пишу, дескать мол:
 
Код:
MyClass = class
  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!
303
10 апреля 2006 года
makbeth
1.0K / / 25.11.2004
Цитата:
Originally posted by Britney
Коллеги, друзья, соратники, программисты! Помогите, пожалуйста!
У меня такой вопрос:
Есть на свете такая штуковина как DLL. Ну мне тоже такую захотелось (потому что действительно нужно). Так вот, будем считать, что в DLL'ке описана одна функция:
 
Код:
function Summ(X,Y:Integer):Integer; StdCall;
begin
  Result:=X+Y;
end;

exports Summ;


Теперь мне надо вызвать ее в программе, и это делается так:
 
Код:
.....
function Summ(X,Y:Integer):Integer; StdCall;
.....
implementanion
function summ; external 'my.dll';
.....

Так работает.

Проблемы начинаются, когда мне надо эту самую функцию из DLL, заставить быть методом моего класса!
пишу, дескать мол:
 
Код:
MyClass = class
  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.

339
10 апреля 2006 года
verybadbug
619 / / 12.09.2005
Вызывай 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;
6.9K
10 апреля 2006 года
Britney
69 / / 20.03.2006
Цитата:
Originally posted by verybadbug
Вызывай dll-функцию из функции класса


К такому решению я уже пришел.

А у меня теперь еще один вопрос:
В dll'ке прописана функция возвращающая строку,пусть так:

 
Код:
function AB(x:integer):string;
begin
  result:=IntToStr(x);
end;
exports AB;


Но когда я вызываю ее на выполнение в программе, то пишется ошибка, вроде как или переполнение стека идет, или еще что-то (нет щас под рукой программы). Я где-то слышал, что не стоит работать c dll с типом данных string, а лучше использовать PChar. Если кто знает, что и почему, то ответьте пожалуйста
339
10 апреля 2006 года
verybadbug
619 / / 12.09.2005
Цитата:
Originally posted by Britney
Я где-то слышал, что не стоит работать c dll с типом данных string, а лучше использовать PChar.



Всё верно...

 
Код:
procedure AB(x:integer;var p: PChar);
begin
  p:= PChar(IntToStr(x));
end;
exports AB;


точно не знаю... нужен var или нет.... пищу без delphi...
6.9K
10 апреля 2006 года
Britney
69 / / 20.03.2006
[QUOTE]Originally posted by verybadbug
А почему все верно?По какой причине нельзя передавать строки в dll и из него?
339
10 апреля 2006 года
verybadbug
619 / / 12.09.2005
Цитата:
Originally posted by Britney
А почему все верно?По какой причине нельзя передавать строки в 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;
...
6.9K
10 апреля 2006 года
Britney
69 / / 20.03.2006
Ну, с этим все более или менее понятно. А теперь хочу задать еще один вопросик: услыхал, что можно создать свой класс в DLL и выдергивать его оттуда, т.е. создать в основной программе переменную типа класса описанного в DLL и юзать ее методы хоть до посинения. Но на практике че-то ниче не выходит. После поисков на другом форуме, кто-то сказанул, что нужно исользовать COM, но что к чему не объяснил. Может кто-нибудь поможет и в этом разобраться?

(А пробовал я сделать следующее: в DLL писал:
Код:
Type
    TMyClass = class
      function MyFun(x:integer):integer; stdcall;
    end;

function TMyClass.MyFun(x:integer):integer;
begin
  result:=x;
end;

exports TMyClass.MyFun;  //Вот здесь-то и возникает ошибка
вроде как пытаюсь экспортировать функцию, в которой используется местный формат.
339
11 апреля 2006 года
verybadbug
619 / / 12.09.2005
тебе сюда....
Создание простого COM-объекта
303
11 апреля 2006 года
makbeth
1.0K / / 25.11.2004
Цитата:
Originally posted by Britney
[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 ;)

339
11 апреля 2006 года
verybadbug
619 / / 12.09.2005
Цитата:
Originally posted by makbeth

Таким образом, если пользуешься типом string, придется таскать вместе с проектом borlandmm.dll ;)




Это лишний геморрой P( ....
На мой взгляд лучше Виндовские типы использовать... Вобщем каждому своё! :}

303
11 апреля 2006 года
makbeth
1.0K / / 25.11.2004
Цитата:
Originally posted by verybadbug
Это лишний геморрой P( ....
На мой взгляд лучше Виндовские типы использовать... Вобщем каждому своё! :}


Дык блин, я и не спорю... просто возможность всетаки есть и о ней надо знать :)

6.9K
11 апреля 2006 года
Britney
69 / / 20.03.2006
Благодарю за исчерпывающие ответы!!!
6.9K
12 апреля 2006 года
Britney
69 / / 20.03.2006
Долго я бился за возможность полноценно использовать Dll в своем проекте, но когда перекинул все функции(около 10) из проекта в DLL, то выяснилось, что программа (самый худший случай -обрабатывается матрица 200*200, причем обработки требует каждый элемент) стала тратить на расчеты вместо 1 секунды около 10 секунд!!!!!Это так и должно быть(зверское затормаживаение) или просто я как-то не так все сделал(сделал я все таким же образом, как было написано выше)? (в моей dll'ке функции в качестве параметров используют динамические массивы и строки PChar). Хотел как лучше, получилось....
5
12 апреля 2006 года
hardcase
4.5K / / 09.08.2005
Цитата:
Originally posted by Britney
Хотел как лучше, получилось....


ХА! если у тебя массив - это массив строк, то я тебе не завидую. И если ты каждую строку конвертишь из string в PChar а в библиотеке - наоборот, то ясен пенть бессмысленное символогоняние будет сильно затормаживать вычисления.

Как вариант - можно использовать пакеты, тогда borlndmm.dll не нужна и все можно передавать "как есть".

6.9K
12 апреля 2006 года
Britney
69 / / 20.03.2006
Цитата:
Originally posted by hardcase
ХА! если у тебя массив - это массив строк, то я тебе не завидую. И если ты каждую строку конвертишь из string в PChar а в библиотеке - наоборот, то ясен пенть бессмысленное символогоняние будет сильно затормаживать вычисления.

Как вариант - можно использовать пакеты, тогда borlndmm.dll не нужна и все можно передавать "как есть".


Ну, да, приходится делать что-то подобное, правда я конвертирую string в PChar и наоборот всего по одному разу за все время исполнения кода. Так что из-за этого не должны лаги появлятся!!! Тут фишка в чем-то другом зарыта, может динамические массивы тоже тормозят вычисления как хрен знает что?
А вот про пакетики можно поподробнее, уж больно мне не охота отказываться от такой козырной штуки, как DLL. Да и вообще уже давно хочется узнать что это такое, да вот все руки не доходили! Заранее благодарю!

10
12 апреля 2006 года
Freeman
3.2K / / 06.03.2004
Цитата:
Originally posted by Britney
А вот про пакетики можно поподробнее, уж больно мне не охота отказываться от такой козырной штуки, как DLL.


Тема уже не раз поднималась на форуме: раз, два, три, четыре, пять, шесть, семь, восемь.

6.9K
13 апреля 2006 года
Britney
69 / / 20.03.2006
Я так понял, что под словом пакет имеется ввиду просто каким-то образом сжатый либо массив, либо запись, либо еще что-то. Т.е. используя слово packed я избавлю свою и без того набитую шишками голову от всяких проблем?(имею ввиду, что смогу передавать string и т.п. в dll и из нее)
5
13 апреля 2006 года
hardcase
4.5K / / 09.08.2005
Цитата:
Originally posted by Britney
Я так понял...

Ты действительно не знаешь элементарного синтаксиса Object Pascal или прикалываешься? :D :D
packed - это резервированное слово для "упаковки" рекордов и массивов (подробнее - RTFM), и отношения к DLL аПсолютно не имеет.

В отношении твоей программы, думаю будет удобнее использовать string в библиотеках в явном виде и пихнуть рядом с приложением библиотеку borlndmm.dll

Пакеты - это *.bpl файлы (фактически тоже библиотеки dll) которые загружаются вместе с исполняемым файлом, и в отличие от обычных dll составляют единое адресное пространство и имеют единый менеджер памяти с экзешником.

6.9K
13 апреля 2006 года
Britney
69 / / 20.03.2006
Цитата:
Originally posted by hardcase
Ты действительно не знаешь элементарного синтаксиса Object Pascal или прикалываешься? :D :D
packed - это резервированное слово для "упаковки" рекордов и массивов (подробнее - RTFM), и отношения к DLL аПсолютно не имеет.

В отношении твоей программы, думаю будет удобнее использовать string в библиотеках в явном виде и пихнуть рядом с приложением библиотеку borlndmm.dll

Пакеты - это *.bpl файлы (фактически тоже библиотеки dll) которые загружаются вместе с исполняемым файлом, и в отличие от обычных dll составляют единое адресное пространство и имеют единый менеджер памяти с экзешником.


Я приколы ловлю в других местах! А так я действительно не знал, что за пакеты имелись ввиду. Но постепенно просвещаюсь. А вот слово packed я нигде кроме как при просмотре подключаемых к unit'у модулей не встречал (но там ведь не написано что, как и зачем, ну только если по-ихнему - по-буржуйски). Я понимаю, что вы считаете, что я либо вечно укуренный чувак, либо человек, который печатает не то что думает (типа я так, - зашел просто потрещать), но нет - я действительно еще очень многого не знаю, потому что берусь за изучение чего-то нового в 3-ёх случаях:
1.Появляется задача, где старыми известными мне методами мне не обойтись, либо очень долго
2.Есть свободное время (это очень редко встречается)
3.Попадается интересная статья или тема на форуме (этот пункт практически полностью зависит от п.2)
Так вот, продолжу. Я сказал, что еще дохрена чё не знаю, например, что за словечки такие ABSTRACT и VIRTUAL. Вычитал где-то, что при их помощи можно экспортировать классы из DLL. Не мог бы кто-нибудь меня просветить, шо да как. (Если несложно то про packed тоже (каким образом это работает и т.д.)

5
13 апреля 2006 года
hardcase
4.5K / / 09.08.2005
Цитата:
Originally posted by Britney
Я сказал, что еще дохрена чё не знаю, например, что за словечки такие ABSTRACT и VIRTUAL. Вычитал где-то, что при их помощи можно экспортировать классы из DLL. Не мог бы кто-нибудь меня просветить, шо да как.

Тебе повезло - я сегодня выспавшийся и обедал. а значит добрый. Смотри проект - там пример создания абстрактного класса и его экспорт из ДЛЛ, а также то же самое, но используя интерфейс.
Про слово packed: в настройках компилятора есть такое свойство, как выравнивание полей классов/записей по байтам (обычно 4 или 8 байтов). если у нас поле занимает 1 байт, то оно будет занимать в памяти эти самые 4 байта. принаписании packed в объявлении записи выравниевание происходит по краям полей и наше поле займёт положенный 1 байт, а не 4. С массивами - аналогично, но, по-моему, для массивов packed включено всегда уже в компиляторе.

6.9K
14 апреля 2006 года
Britney
69 / / 20.03.2006
Цитата:
Originally posted by hardcase
Тебе повезло - я сегодня выспавшийся и обедал. а значит добрый.


Да ты очень хорошо выспался и пообедал!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Очень признателен за столь ценный и информативный подарочек! Буду его хранить до следующего форматирования точно!

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог