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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Преобразование классовых методов в процедуры, regular procedure and method pointer 
:(
    Опции темы
BofA
Дата 7.5.2008, 12:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Доброго времени суток, дорогие друзья! Требуется ваша помощь.
Итак, имеется DLL (исходников DLL нет), которая экспортирует следующую функцию:
Код
function SET_CALLBACK(pfStatusCallback: STATUS_CALLBACK; var pnExtendedErrorCode: LongInt; lpstrErrorMessage: LPSTR; dwErrorMessageSize: DWORD): longint; stdcall;

где STATUS_CALLBACK объявлена как
Код
STATUS_CALLBACK = procedure (nConnectionEvent: Longint; nExtendedErrorCode: Longint; lpcstrInfoMessage: LPCSTR); stdcall;

Непосредственно в моей программе имеется класс
Код
TMyClass = class(TThread)
  private
    procedure StatusCallback(nConnectionEvent: Longint;
      nExtendedErrorCode: Longint; lpcstrInfoMessage: LPCSTR); stdcall;
    ...
  public
    constructor Create;
    ...
  end;

Соответственно в конструкторе класса хочется написать что-то вроде
Код
SET_CALLBACK(StatusCallback, ErrorCode, Buf, SizeOf(Buf));

дабы объяснить DLLке, что в качестве callback функции нужно использовать классовую функцию StatusCallback, но компилятор закономерно выдаёт "Incompatible types: 'regular procedure and method pointer'". Соответственно, если объявлять функцию StatusCallback вне класса, то всё работает, но этот вариант не подходит. Поскольку исходников DLL нет, то дописать "of object" к объявлению типа STATUS_CALLBACK невозможно.
Посему подскажите пожалуйста, как можно разрешить данную проблему и передать классовый метод StatusCallback как обычную функцию.
PM MAIL   Вверх
MetalFan
Дата 7.5.2008, 13:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

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



имхо невозможно в данном случае. ибо первым параметром в процедуру-метод неявно передается ссылка на объект.



--------------------
There are always someone smarter than you...
PM MAIL   Вверх
Rennigth
Дата 7.5.2008, 13:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



BofA
Попробуй передавать так:
Код

  SET_CALLBACK(TMethod(StatusCallback).Code, ErrorCode, Buf, SizeOf(Buf));

Может проглотит...

Добавлено через 3 минуты и 10 секунд
туплю, перепутал, немного не так, ща...  smile

Добавлено через 6 минут и 10 секунд
Код

  SET_CALLBACK(STATUS_CALLBACK(TMethod(StatusCallback).Code), ErrorCode, Buf, SizeOf(Buf));

Не проверял правда smile


--------------------
(* Honesta mors turpi vita potior *)
PM MAIL ICQ   Вверх
BofA
Дата 7.5.2008, 13:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



MetalFan
Надежда умирает последней smile Хочется верить, что нет ничего невозможного  smile 


Rennigth
Компилятор ругается на преобразование TMethod(StatusCallback) - говорит "Invalid typecast"  smile

Это сообщение отредактировал(а) BofA - 7.5.2008, 13:19
PM MAIL   Вверх
Rennigth
Дата 7.5.2008, 13:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



BofA, а так:
Код

type
  TStatusCBEvent = procedure StatusCallback(nConnectionEvent: Longint;
     nExtendedErrorCode: Longint; lpcstrInfoMessage: LPCSTR) of object; stdcall;
var
  lProc: TStatusCBEvent;
begin
  lProc := StatusCallback;
  SET_CALLBACK(STATUS_CALLBACK(TMethod(lProc).Code), ErrorCode, Buf, SizeOf(Buf));
...
end;

?


--------------------
(* Honesta mors turpi vita potior *)
PM MAIL ICQ   Вверх
BofA
Дата 7.5.2008, 14:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Rennigth
Получился весьма интересный эффект  smile 
Программа компилируется, DLL осознаёт, что надо использовать StatusCallback, но когда происходит событие и DLLка 

вызывает эту функцию, то
а) переменные не передаются (все равны нулю)
б) возникает Access violation
Ради эксперимента убрал stdcall у StatusCallback, и переменные почему-то начали передаваться, но Access violation 

остался.

P.S.: StatusCallback выглядит так
Код

procedure TMyClass.StatusCallback(nConnectionEvent: Longint;
      nExtendedErrorCode: Longint; lpcstrInfoMessage: LPCSTR);
begin
  FLastErrorMsg := IntToStr(nConnectionEvent);
end;

Ставлю точку останова на единственной строчке процедуры,  эта строчка отрабатывает, а после этого вылезает Access 

violation.
PM MAIL   Вверх
MetalFan
Дата 7.5.2008, 14:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

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



Rennigth, я уже говорил, что при вызове метода первым неявным параметром должен идти указатель на объект.

Цитата(BofA @  7.5.2008,  14:12 Найти цитируемый пост)
вызывает эту функцию, то
а) переменные не передаются (все равны нулю)
б) возникает Access violation

это происходит потому, что вместо ожидаемого указателя на объект приходит черте-че (nConnectionEvent), соотв Self не доступен и все параметры сдвинуты.


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
BofA
Дата 7.5.2008, 14:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



MetalFan
Неужели сие никак нельзя обойти? Наверняка ведь должен быть способ подсунуть этот самый "первый неявный параметр"?
PM MAIL   Вверх
MetalFan
Дата 7.5.2008, 14:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

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



з.ы. в свое время мне понадобилось следующее: поставить обработчиком события не метод класса, а просто процедуру.
сделано было что-то типа:
Код

 ...
procedure ButtonClickHandler( Self: TObject; Sender: TObject );
begin
  ShowMessage( TButton(Self).Caption );
end;

procedure TdmTest.FormCreate(Sender: TObject);
var
  lMethod: TMethod;
begin
  lMethod.Code := @ButtonClickHandler;
  lMethod.Data := Btn;
  btn.OnClick := TNotifyEvent( lMethod );
end;




--------------------
There are always someone smarter than you...
PM MAIL   Вверх
Rennigth
Дата 7.5.2008, 14:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(MetalFan @  7.5.2008,  14:18 Найти цитируемый пост)
Rennigth, я уже говорил, что при вызове метода первым неявным параметром должен идти указатель на объект.

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

Добавлено через 42 секунды
MetalFan, я про тоже  smile 


--------------------
(* Honesta mors turpi vita potior *)
PM MAIL ICQ   Вверх
BofA
Дата 7.5.2008, 14:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Основная проблема в том, что нет доступа к функции SET_CALLBACK, описанной в DLL. В описанных же Вами примерах был доступ к той функции, которая занимается непосредственно присвоением метода, поэтому простор для экспериментов был больше. Здесь же я не могу объяснить функции SET_CALLBACK, что ей передаётся метод, где первым идёт неявный параметр - указатель, поэтому SET_CALLBACK тупо забивает в этот неявный параметр то, что должно было попасть, например, в nConnectionEvent ( MetalFan, я правильно понимаю? ) Неужели данная проблема действительно не имеет решения?
PM MAIL   Вверх
MetalFan
Дата 7.5.2008, 14:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

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



Цитата(Rennigth @  7.5.2008,  14:41 Найти цитируемый пост)
что и тут можно выкрутиться

если исходники DLL недоступны, то имхо таким способом не выйдет...


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
dumb
Дата 7.5.2008, 15:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

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



через "переходник" можно сделать: смотреть здесь на реализацию TLiteFrame.Create
PM MAIL   Вверх
BofA
Дата 7.5.2008, 15:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



dumb
К сожалению, я не знаю ассемблера  smile 
Не могли бы Вы чуть подробнее осветить данный вопрос?
PM MAIL   Вверх
dumb
Дата 7.5.2008, 16:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

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



там не обязательно знать ассемблер. просто "слизывай" реализацию установки call-back'а.
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

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

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

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

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


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

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


 




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


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

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