【发布时间】:2014-07-06 03:16:03
【问题描述】:
我正在使用需要 Callback 的 JNA 接口。我有原生函数g 的原始地址,这是我想作为回调安装的函数。我正在调用本机函数f,它需要一个回调,并且我希望JNA 将我的原始指针编组为g 作为回调,只需将g 的地址传递给f。 JNA 可以做到这一点吗?
插图
这是我的意思的具体说明。我正在使用 Win32,我想注册一个默认窗口过程为DefWindowProc 的窗口类。在普通课程中,我会在 C 中执行以下操作来注册一个具有默认窗口过程的窗口类:
WNDCLASSEX wcex;
ZeroMemory(&wcex, sizeof(WNDCLASSEX));
wcex.cbSize = sizeof(WNDCLASSEX);
...
wcex.lpfnWndProc = LoadLibrary("user32", "DefWindowProcA");
...
ATOM atom = RegisterClassEx(&wcex);
但是,有时我想用不同的窗口过程注册一个窗口类。在 C 中,我会完全按照上面的方式做,除了:
wcex.lpfnWndProc = MyWindowProc; // Address of my custom window procedure
希望现在可以清楚 JNA 的难点所在。我正在编写类似于以下内容的 Java 代码:
WNDCLASSEX wcex = new WNDCLASSEX.ByReference();
wcex.cbSize = WNDCLASSEX.size();
...
wcex.lpfnWndProc = new MyWindowProc(); // where MyWindowProc implements the Callback interface;
// but what if I want to just set it to the address of
// DefWindowProcA?
ATOM atom = User32.RegisterClassEx(wcex);
警告
我知道我可以在 Java 中定义函数f 的两个替代版本,其中一个采用Callback,另一个采用Pointer,并将我的地址传递给g Pointer 版本。我也知道我可以为 DefWindowProcA 创建一个“包装回调”。由于各种原因,这些都不是适当的解决方案。
【问题讨论】:
-
写一个适配器。编写调用函数指针的回调实现。
-
@David 请从头到尾阅读问题。 OP 已经表示他们不认为“包装回调”方法是可以的。此外,这也是我的答案的初始迭代的解决方法,OP 明确评论说他们想要不同的东西。
-
@Chris 我可以阅读。只是需要按照我说的方式进行。我看不出原始指针如何成为
Callback。 -
@DavidHeffernan 在基本层面上(即,如果您超越 JNA),回调 是 指针。在 JNA 级别,它们当然不一样,因为
Callback有一个this指针,而Pointer(更具体地说,Function)没有。但是,通过我的帖子使用的编组/解组方法,JNA 为Callback创建了一个代理对象,使其能够正确委托。 -
@DavidHeffernan(还有 OP):我已经编写了一个有趣的小程序来测试回调,包括 Java 端的以及类型化的 C 端的:gist.github.com/cky/7397db4908fa9616539b