Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Indy и DLL и Access Violation, Помогите найти причину и исправить 
V
    Опции темы
Kelas
Дата 31.8.2006, 17:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 2
Регистрация: 31.8.2006

Репутация: нет
Всего: нет



Мне по учебе нужно добавить к проекту DLL. Проэкт - база данных, работающая с клиентами с помощью компонентов TIdTCPClient и TIdTCPServer - этакая удаленная база вручную. Я решил перенести все функции работы с этими компанентами в DLL. Создал новый проект DLL-ки, добавил к uses юнит с процедурками и выписал все нужные в Exports. Все нормально скомпилировалось, я подключил библиотеку к проекту функцией LoadLibrary и для начала заменил функцию которая стучится по указанному порту и адрсу к серверу и проверяет, есть ли там вто живой. 

Вот эта функция:

Код

function InitServer (var P : Pointer) : Boolean;
var
  TCP : ^TIdTCPClient;
begin
if P<>nil then
  begin
    TCP := P;
    with TCP^ do
      begin
        try
          try
            Connect;
            WriteInteger(taInitCheck); //  taInitCheak = 0;
            if (ReadInteger = trSuccess) then //trSuccess = 1;
              Result := true
            else
              Result := false;
          except
            on EIdSocksError do
              Result := false;
            on EIdException do
              Result := false;
            on E:Exception do
              ShowMessage(E.Message);
          end;
        finally
          Disconnect;
        end;
      end
  end
else
  Result := false;
end;


А вот код в проекте где вытаскивается она из DLL и вызыается:

Код

procedure TLForm.Button2Click(Sender: TObject);
var
  TIS : function(var P: Pointer):Boolean;
  P : Pointer;
begin
{...}
      @TIS := GetProcAddress(GetModuleHandle('KB_TCP.dll'),'InitServer');
      if @TIS = nil then ShowMessage('...');
      P := @CruiserForm.cTCP;
      if NOT TIS(P) then
        begin
          MsgDlg.Text := 'Сервер на отвечает';
          MsgDlg.ShowModal;
        end
{...}
end;


Во время работы функции возникает Access Violation c чтением нулевого адреса, на строчке "WriteInteger(taInitCheck);" в модуле KB_TCP.dll

Если та же функция, слово в слово будет использоваться в проекте, тоесть как бы локально, а не вызываться из DLL то никаких ошибок не возникает и все работает как часы... 




PM MAIL   Вверх
Yanis
Дата 1.9.2006, 09:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2937
Регистрация: 9.2.2004
Где: Москва

Репутация: 72
Всего: 111



Что такое CruiserForm.cTCP?


--------------------
user posted image *щёлк*
PM MAIL WWW ICQ   Вверх
Matematik
Дата 1.9.2006, 09:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1027
Регистрация: 11.3.2006

Репутация: 17
Всего: 50



CruiserForm.cTCP это кажется TIdTCPClient
По мне сомнительная операцие передавать в dll указателлльна экземпляк объекта и там с ним работать...
PM MAIL WWW ICQ   Вверх
Snowy
Дата 1.9.2006, 09:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 192
Всего: 484



dll и передача объектов - понятия несовместимые.
Используй bpl или выделяй в dll только полностью отделённый логический код.
Хотя в принципе непонятно, зачем тебе вообще dll?
PM MAIL   Вверх
Yanis
Дата 1.9.2006, 09:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2937
Регистрация: 9.2.2004
Где: Москва

Репутация: 72
Всего: 111



Kelas
Попробуй мой метод загрузки. Должно получиться smile

Цитата(Kelas @  31.8.2006,  18:51 Найти цитируемый пост)
@TIS := GetProcAddress(GetModuleHandle('KB_TCP.dll'),'InitServer');

Для загрузки библиотеки лучше использовать LoadLibrary. Стоит переделать процедуру нажатия на кнопку, что бы она приняла приблизительно такой вид:
Код
var
  P: Pointer;
  TIS: function(var P: Pointer): Boolean;
  hLib: DWORD;
begin
  hLIb := LoadLibrary('KB_TCP.dll');
  if hLib > 0 then
    begin // библиотека подгрузилась
      TIS := GetProcAddress(hLib, 'InitServer');

      if @TIS = nil then
        begin // не удалось получить адрес функции
          FreeLibrary(hLib);
          Exit;
        end;

      // адрес функции получен
      // можно её вызывать
      P := @IdTCPClient1;
      if not TIS(P) then
        begin
          //MsgDlg.Text := 'Сервер на отвечает';
          //MsgDlg.ShowModal;
        end;

      // если мы до сюда добрались, то
      // библиотека была подгружена и надо её отпустить
      FreeLibrary(hLib);
    end;
end;



Это сообщение отредактировал(а) Yanis - 1.9.2006, 09:44


--------------------
user posted image *щёлк*
PM MAIL WWW ICQ   Вверх
Kelas
Дата 1.9.2006, 17:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 2
Регистрация: 31.8.2006

Репутация: нет
Всего: нет



Спасибо Yanis, твой метод работает, однако проблема была не в этом, с загрузкой библиотеки и получением адреса функции у меня проблем не было, я тоже грузил библиотеку с помощью LoadLibrary просто происходило это не в функции обработки кнопки.

Проблема как сказал Snowy, и подозревал Matematik, в том, что я работал с методами объекта. Странно конечно, что функция Connect все равно срабатывала без ошибок, но WriteInteger он, несмотря на это, не переваривал.

Я переделал функцию - просто созал "локального клиента" в функции и передал Host и Port в него с помощью уже передававшегося указателя - читает он вроде без Access Violation'ов.

Вот итоговый код функции, если это кому-то интересно:

Код

function InitServer (var P : Pointer) : Boolean;
var
  pTCP : ^TIdTCPClient;
  TCP : TIdTCPClient;
begin
if P<>nil then
  begin
    pTCP := P;
    TCP := TIdTCPClient.Create(nil);
    TCP.Host := pTCP^.Host;
    TCP.Port := pTCP^.Port;
    with TCP do
      begin
        try
          try
            Connect;
            WriteInteger(taInitCheck);
            if (ReadInteger = trSuccess) then
              Result := true
            else
              Result := false;
          except
            on EIdSocksError do
              Result := false;
            on EIdException do
              Result := false;
            on E:Exception do
            begin
              Result := false;
              ShowMessage(E.Message);
            end;
          end;
        finally
          Disconnect;
        end;
      end;
    TCP.Destroy;
  end
else
  Result := false;
end;

PM MAIL   Вверх
Snowy
Дата 1.9.2006, 17:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 192
Всего: 484



Просто класс, скомпиленный в exe и он же скомпиленный в dll - это уже 2 разных класса.
Для готового кода они совсем не равны.
Класс и работа с ним должны быть описаны в одном месте - либо в dll, либо в exe.

Добавлено @ 17:56 
Цитата(Kelas @  1.9.2006,  17:40 Найти цитируемый пост)
функция Connect все равно срабатывала без ошибок, но WriteInteger он, несмотря на это, не переваривал.
Потому что Connection прописана в виртуальной таблице, а WriteInteger фиксированно.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0535 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.