Ситуация такова: у меня есть сканер штрих-кода с dll (написанный на C++, все функции stdcall), который экспортирует все необходимые функции для связи с ним. И есть несколько функций, которые следует использовать для назначения в качестве обратных вызовов (я должен предоставить соответствующие процедуры, и они будут вызваны, как только произойдет определенное событие). И вот главная проблема, с которой я столкнулся. Эти функции назначения обратного вызова могут принимать только «автономные» процедуры (в этом случае все работает нормально), но не методы или даже анонимная процедура. На этих событиях мне приходится обращаться к некоторым данным класса (сканер реализуется как класс), например, полям и методам, но обычно это невозможно из процедуры отдельного блока. Можете ли вы помочь мне решить эту проблему?Процедура отправки экспортированной DLL-функции (организация обратного вызова)
Некоторый код:
Описания сканера API:
typedef void (__stdcall *TOnDevicePlug)(bool PluggedIn);
extern "C" __declspec(dllexport) void __stdcall SetupOnDevicePlugCallback(TOnDevicePlug OnPresent);
Мои описания типа:
TOnDevicePlug = procedure(PluggedIn: Boolean); stdcall;
TSetupOnDevicePlugCallback = function(AOnPresent: TOnDevicePlug): Integer; stdcall;
В случае, если я вот так:
procedure OnDevicePlug(PluggedIn: Boolean); stdcall;
begin
Form2.mmLog.Lines.Add('On plugged activated');
end;
...
@FSetupOnDevicePlugCallback := GetProcAddress(FDllHandle, 'SetupOnDevicePlugCallback');
FSetupOnDevicePlugCallback(OnDevicePlug);
...
Все работает. (Но опять же, я не могу работать с моим классом).
Если я пытаюсь что-то вроде этого:
FOnPlug := TOnDevicePlug(
procedure stdcall
begin
mmLog.Lines.Add('On plugged activated');
end
);
FSetupOnDevicePlugCallback(FOnPlug);
Где FOnPlug - поле класса типа TOnDevicePlug. В этом случае есть два варианта: если я оставляю описание старого типа (TOnDevicePlug = procedure(PluggedIn: Boolean); stdcall;
), я получаю исключение из «привилегированной инструкции». Если я изменю тип на «ссылка на процедуру» (например, TOnDevicePlug = reference to procedure stdcall;
), я получаю исключение нарушения прав доступа. Эти ошибки вызывают событие.
Так вы можете посоветовать мне что-то, чтобы это мероприятие работало с моим классом? Будем благодарны за любую идею. Или, может быть, вы увидите некоторые ошибки в моем коде.
Вы не * должны написать процедуру с ограниченной единицей *. Вы можете использовать метод статического класса. Но вы до сих пор не получите доступ к * этому * экземпляру. Это тесно связано с http://stackoverflow.com/q/2953070/960757. – TLama
@TLama Да, статический класс способ тоже возможно. –
Большое спасибо за ответ. К сожалению, редактировать эту библиотеку невозможно. Я решил использовать глобальную переменную (не лучшее решение, но ...).С другой стороны кажется, что нет никакой возможности подключить два таких устройства к одной системе, поэтому решение вполне приемлемо. –