Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Для новичков > Dll


Автор: MrDmitry 7.9.2011, 02:08
Блин, уже сломал всю голову, облазил нет а ответа так и не нашол, хотя вопрос нубский. 


Есть такая функция


Код

function TMains.query(http, login, password:string):string;
  var
   data: TIdMultiPartFormDataStream;
   n:integer;
   xml1,res:string;
  begin
    data := TIdMultiPartFormDataStream.Create;
  try
     res:=mains.IdHTTP1.get(http+'action=1&login='+login+'&password='+password);
      n := Pos('<name>', res);
      xml1 := Copy(res, n + 6, length(res));
      n := Pos('</name>', xml1);
     name_s:=Copy(xml1, 1, n-1);
     n:=Pos('<surname>', res);
     xml1:=Copy(res, n+9, length(res));
     n:=Pos('</surname>', xml1);
     surname:=Copy(xml1, 1, n-1);
     n:=Pos('<patronymic>', res);
     xml1:=Copy(res, n+12, length(res));
     n:=Pos('</patronymic>', xml1);
     patronamic:=Copy(xml1, 1, n-1);
  finally
    data.Free;
  end;
  end;


Функция отправляет запрос на сервер, получает xml ответ, парсит его и получает фио вошедшего. 

Данную функцию решил перенести в dll


l
Код

ibrary proc;

{ 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. }

uses
 ShareMem, 
 Windows,
  Messages,
  SysUtils,
  Variants,
  Classes,
  Graphics,
  Controls,
  Forms,
  Dialogs,
  IdBaseComponent,
  IdComponent,
  IdTCPConnection,
  IdTCPClient,
  IdHTTP,
  StdCtrls,
  IdMultipartFormData,
  modules in 'modules.pas' {DataModule3: TDataModule};

function query(http, login, password:string):string; stdcall; export;
  var
   data: TIdMultiPartFormDataStream;
   n:integer;
   xml,res:string;
  begin
    data := TIdMultiPartFormDataStream.Create;
  try
     res:=datemodule1.IdHTTP1.get(http+'action=1&login='+login+'&password='+password);
     name_s:=Copy(xml1, 1, n-1);
     n:=Pos('<surname>', res);
     xml1:=Copy(res, n+9, length(res));
     n:=Pos('</surname>', xml1);
     surname:=Copy(xml1, 1, n-1);
     n:=Pos('<patronymic>', res);
     xml1:=Copy(res, n+12, length(res));
     n:=Pos('</patronymic>', xml1);
     patronamic:=Copy(xml1, 1, n-1);
  finally
    data.Free;
  end;
  end;

 Exports query;
begin
end.


на датамодуле разместил IdHTTP1

вызов 


Код

....
implementation
query(http, login, password:string):string; stdcall; external 'proc.dll';
....

procedure TMains.standartClick(Sender: TObject);
begin
query('http://sayte.ru/index.php?',' test', 'test');
end;


модуль ShareMem в самом проекте также подключен (Через project > view source)

ошибка http://s1.ipicture.ru/Gallery/Viewfull/5754154.html

Что не так?

Автор: Keeper89 7.9.2011, 02:48
Нельзя так строки передавать. Прочитай конец сгенерированного комментария.

Автор: rodnover 7.9.2011, 06:39
Цитата

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


Вот ключ к разгадке. smile

Автор: bems 7.9.2011, 20:57
Ничего не ясно:
1) что такое TMains?
2) как ты умудряешься экспортировать из библиотеки метод объекта? (ключевое слово export не экспортирует, для этого есть слово exports, но применяется оно иначе)
3) как при этом ты импортируешь его в программе как простую функцию? (фактически это означает разный список параметров)

Автор: MrDmitry 8.9.2011, 08:54
Цитата(bems @ 7.9.2011,  20:57)
Ничего не ясно:
1) что такое TMains?
2) как ты умудряешься экспортировать из библиотеки метод объекта? (ключевое слово export не экспортирует, для этого есть слово exports, но применяется оно иначе)
3) как при этом ты импортируешь его в программе как простую функцию? (фактически это означает разный список параметров)

1. Tmains - это форма просто в отрывки я показал как вызываю функцию кликом по кнопки
2. Вот тут вот поподробнее. Как раз тут скорее всего и есть косяк. Как я писал в 1 посте, просто тупо создал дата модуль кинул на него IdHTTP и все. Как сделать dll библиотеку, с учетом что нужно работать с IdHTTP?
3 Почему как простую функцию? После implementation я описываю функцию указывая что она внешняя и находится в библиотеке proc.dll. Это вроде называется Статическая загрузка dll

Автор: bems 8.9.2011, 09:42
Цитата(MrDmitry @  8.9.2011,  08:54 Найти цитируемый пост)
Как сделать dll библиотеку, с учетом что нужно работать с IdHTTP?
Бмблиотеку сделать просто - так как ты и сделал, но не пытаться экспортировать метод объекта, а экспортировать обычную функцию.
Тут в другом вопрос - как эта длл у тебя вообще компилируется? До Access Violation при вызове дойти не должно, потому что вот это
Код

 Exports query;
ссылается на неизвестный идентификатор query. Да, TMains.query это совсем другое. Или у тебя есть query в интерфейсной секции юнита modules, или это не компилится.
Цитата(MrDmitry @  8.9.2011,  08:54 Найти цитируемый пост)
 Почему как простую функцию? После implementation я описываю функцию указывая что она внешняя и находится в библиотеке proc.dll. Это вроде называется Статическая загрузка dll 

Да, это так называется. Но экспортируешь ты метод объекта (вернее пытаешься экспортировать), а импортируешь простую функцию (не метод объекта). Если бы она нормально экспортировалась, это была бы ошибка во время выполнения, потому что у методов есть один неявный параметр при вызове (Self), а импорт с несовпадающим списком параметров это проблема.
Вообще экзешник не должен запуститься, потому что query не найдется в нужной длл (поскольку экспорт так не делается). И тут ты опять что-то темнишь, если говоришь что оно запускается, но падает с исключегнием

Автор: MrDmitry 8.9.2011, 11:26
Ну компилируется, и создается длл без ошибок. При запуски exe вылатает ошибка из 1 поста, и вылатает каждый раз когда я вызываю функцию query

ЗЫ сорри немного ввел вас в заблуждения, т.к dll у меня не работает, я оставил все как есть и данную функцию копировал с проекта, при этом забыв убрать TMains, естественно в проекта DLL функция записана так 
Код

function query(http, login, password:string):string; stdcall; export



Автор: bems 8.9.2011, 12:05
Где создаётся объект datemodule1?

Автор: MetalFan 8.9.2011, 12:16
В общем есть пара замечаний, читай - ошибок, по коду.
Смотрим функцию query, что перенесена в dll...
1. зачем stdcall? планируется ее использование в приложениях, написанных не на делфи?
2. зачем data: TIdMultiPartFormDataStream, которая ни где не используется?
3. вторая строка после try:  name_s:=Copy(xml1, 1, n-1); что есть xml1? что есть n? неинициализированные локальные переменные в которых лежит мусор. похоже, что не хватает строк по определению n и xml1.

Дальше смотреть смысла не вижу.

Автор: MrDmitry 8.9.2011, 12:38
Цитата(MetalFan @ 8.9.2011,  12:16)
В общем есть пара замечаний, читай - ошибок, по коду.
Смотрим функцию query, что перенесена в dll...
1. зачем stdcall? планируется ее использование в приложениях, написанных не на делфи?
2. зачем data: TIdMultiPartFormDataStream, которая ни где не используется?
3. вторая строка после try:  name_s:=Copy(xml1, 1, n-1); что есть xml1? что есть n? неинициализированные локальные переменные в которых лежит мусор. похоже, что не хватает строк по определению n и xml1.

Дальше смотреть смысла не вижу.

Извините за мою расторопность, я не до конца скопировал код функции исправил в 1 посте. 
Код

data := TIdMultiPartFormDataStream.Create;
  try
   ...
 finally
    data.Free;
  end

Разве TIdMultiPartFormDataStream ни где не используется? И да, начал переписывать функцию в длл т.к планируется её использование не только в этом проекте и не только на Delphi
bems Как я уже писал как раз таки в этом скорее всего и есть моя ошибка которую я не знаю как решить. И как опять же я писал выше, я просто создал datamodule(New > datamodule) и кинул на него idhttp

Автор: bems 8.9.2011, 12:54
Цитата(MrDmitry @  8.9.2011,  12:38 Найти цитируемый пост)
я просто создал datamodule(New > datamodule) и кинул на него idhttp 
ну конечно он не создан.
Создай экземпляр до того как будет вызвана любая экспортируемая функция в длл (в DLL_PROCESS_ATTACH) и освобождай его при выгрузке длл (в DLL_PROCESS_DETACH)

что это такое ты можешь узнать из многочисленных книг и статей на эту тему

Добавлено через 2 минуты и 15 секунд
Цитата(MrDmitry @  8.9.2011,  12:38 Найти цитируемый пост)
не только в этом проекте и не только на Delphi
тогда убирай ShareMem из uses и дельфи-специфичные типы из параметров экспортируемых функций

Автор: MrDmitry 8.9.2011, 13:03
Цитата(bems @ 8.9.2011,  12:54)
Цитата(MrDmitry @  8.9.2011,  12:38 Найти цитируемый пост)
я просто создал datamodule(New > datamodule) и кинул на него idhttp 
ну конечно он не создан.
Создай экземпляр до того как будет вызвана любая экспортируемая функция в длл (в DLL_PROCESS_ATTACH) и освобождай его при выгрузке длл (в DLL_PROCESS_DETACH)

что это такое ты можешь узнать из многочисленных книг и статей на эту тему

Добавлено @ 12:57
Цитата(MrDmitry @  8.9.2011,  12:38 Найти цитируемый пост)
не только в этом проекте и не только на Delphi
тогда убирай ShareMem из uses и дельфи-специфичные типы из параметров экспортируемых функций

А вот это для меня уже сложно или я чего то не допанемаю, как все это делается? Или где про это можно почитать?

Автор: bems 8.9.2011, 13:21
Первая ссылка по запросу "DLL_PROCESS_ATTACH в дельфи" в гугле ведет сюда http://delphi.about.com/cs/adptips2003/a/bltip1003_2.htm

Автор: bems 8.9.2011, 13:39
Хотя чтоб попроще, ты можешь использовать секции initialization и finalization юнита где объявлен датамодуль

Автор: MrDmitry 8.9.2011, 14:09
Цитата(bems @ 8.9.2011,  13:39)
Хотя чтоб попроще, ты можешь использовать секции initialization и finalization юнита где объявлен датамодуль

Блин. Как получается все это сложно :( Давайте попробуем пойти другим путём. Как можно отсылать get запрос не используя сторонних компонентов, таких как idhhtp в данном примере

Автор: bems 8.9.2011, 14:33
initialization и finalization это очень просто, если прочитать книгу где описан язык.
компоненты indy можно использовать и без форм и датамодулей (создавая динамически)

Один топик - один вопрос

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)