向导出的dll函数发送过程(组织回调)

时间:2015-06-11 13:11:05

标签: delphi delphi-xe2

情况是这样的:我有一个带有dll的条形码扫描器(用C ++编写,所有函数都是stdcall),它输出所有必要的函数来与之通信。并且有几个函数应该用于分配回调(我必须提供适当的过程,并且一旦某些事件触发就会调用它们)。这是我面临的主要问题。这些回调分配功能只能接受“独立”程序(在这种情况下一切正常),但不接受方法甚至是匿名程序。在这些事件中,我必须访问一些类数据(扫描仪实现为类),如字段和方法,但通常不能从独立的单元过程。你能帮我解决这个问题吗?

一些代码:

扫描仪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;),则会出现访问冲突异常。这两个错误都是在事件中触发的。

那么你可以告诉我一些事情,让这个活动与我的班级一起工作吗?任何想法都会感激不尽。或许你会在我的代码中看到一些错误。

1 个答案:

答案 0 :(得分:1)

您的回调必须采用以下格式:

procedure MyOnDevicePlug(PluggedIn: Boolean); stdcall;
begin
  // do stuff
end;

匿名方法根本不兼容。写一个单位范围的程序,如下所示:

var express = require('express'),
request = require('request'),
bodyParser = require('body-parser');

var app = express();

function createMainPage (req, res, msg) {

res.setHeader('Content-Type', 'text/html; charset=utf-8');
var result = '<html><head><script src="http://code.jquery.com/jquery-migrate-1.2.1.min.js"></script>';
result += '<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">';
result += '<link rel="stylesheet" href="https://bootswatch.com/cerulean/bootstrap.min.css">';
result += '<title> Demo </title>';
result += '</head><body><br /><br /><br /><div class="container">';
result += '<form class="form-horizontal" method="post"><fieldset><legend> Demo </legend>';
result += '<br /><h2><center>Please enter your Phone Number</center></h2> <br /> <br />';
result += '<div class="col-lg-2 col-lg-offset-5">';
result += '<input type="text" class="form-control" id="inputphonenumber" name="inputphonenumber"placeholder="+33XXXXXXXXX"></div>';
result += '</fieldset></div><br/><p style="text-align:center; font-weight:700; font-size:1.2em;">' + msg + '</dialog></p><br /><br /><br />';
//
//msg here is the parameter that i want to show on a modal windows after click on submit button
//
result += '<div class="form-group"><div class="col-lg-10 col-lg-offset-6">';
result += '<button type="reset" class="btn btn-default">Cancel</button>';
result += '<button type="submit" class="btn btn-primary">Submit</button></form>';
result += '<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>';

result += '</body></html>';
res.send(result);
}

app.set('port', (process.env.PORT || 8080)); // cannot force 80
app.use(bodyParser.urlencoded({extended: false}));
app.use(express.static(__dirname + '/public'));
app.get('/', function(req, res, next) {createMainPage(req, res, "")
});

app.post('/', function(req, res, next) {
var myText = req.body.inputphonenumber;

//...... 
// I do some operations to finally get the parameter "message"
//......

createMainPage(req, res, customMessage);}

app.listen(app.get('port'), function() {
console.log('userDetails Node app is running on port',      
app.get('port'));
});

现在,您正在使用的库在调用此回调时不会提供任何其他信息。它不传递额外的指针,以允许回调接收者访问其状态。

您可以修改您使用的库,以便在调用它时接受无类型指针,然后在回调中将该指针传递给您。

如果你不能进行这样的修改,那么你可能需要使用全局变量,甚至thunk来获得状态。