我正在使用一个 JNA 接口(interface),它需要 Callback
。我有 native 函数 g
的原始地址,这是我想要作为回调安装的函数。我正在调用 native 函数 f
,它需要回调,并且我希望 JNA 通过仅传递 的地址来将我的原始指针编码为
到 g
作为回调gf
。 JNA 可以做到这一点吗?
插图
这是我的意思的具体说明。我正在使用 Win32,并且想要注册一个窗口类,其默认窗口过程是 DefWindowProc
。在普通类(class)中,我会在 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 创建一个“包装回调”。由于各种原因,这些都不是足够的解决方案。
最佳答案
为了能够使用外部指针作为回调
,您可以像 C 程序员那样使用双关语:使用联合。
public static class WindowProcUnion extends Union {
public Pointer ptr;
public WinUser.WindowProc wndProc;
public WindowProcUnion(Pointer ptr) {
this.ptr = ptr;
setType("ptr");
write();
setType("wndProc");
read();
}
}
您现在可以读取 wndProc
字段并获取可用的窗口过程回调。
对于此用例,DefWindowProc
实际上是通过 User32
类导出的,因此您只需创建一个回调即可直接调用它:
public static class DefWindowProc implements WinUser.WindowProc {
@Override
public LRESULT callback(WinDef.HWND hWnd, int uMsg, WinDef.WPARAM wParam, WinDef.LPARAM lParam) {
return User32.INSTANCE.DefWindowProc(hWnd, uMsg, wParam, lParam);
}
}
看看 Win32WindowDemo
class有关委托(delegate)给 DefWindowProc
的窗口过程的示例。
关于java - 在 JNA 定义需要回调的地方传递原始函数指针?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24592403/