[英]Pass a raw function pointer where the JNA definition expects a Callback?
I'm working with a JNA interface that expects a Callback
. 我正在使用需要Callback
的JNA接口。 I have the raw address of a native function g
, which is the function I want to install as a callback. 我有本机函数g
的原始地址,这是我要安装为回调的函数。 I am calling native function f
, which expects a callback, and I would like JNA to marshall my raw pointer to g
as the callback by just passing the address of g
through to f
. 我正在调用本机函数f
,该函数需要一个回调,并且我希望JNA通过将g
的地址仅传递给f
来将我的原始指针g
编组为回调。 Is this possible with JNA? JNA有可能吗?
ILLUSTRATION 插图
Here's a concrete illustration of what I mean. 这是我的意思的具体说明。 I'm working with Win32 and I want to register a window class whose default window procedure is DefWindowProc
. 我正在使用Win32,我想注册一个窗口类,其默认窗口过程为DefWindowProc
。 In the ordinary course I would do the following in C to register a window class having the default window procedure: 在通常的过程中,我将在C中执行以下操作以注册具有默认窗口过程的窗口类:
WNDCLASSEX wcex;
ZeroMemory(&wcex, sizeof(WNDCLASSEX));
wcex.cbSize = sizeof(WNDCLASSEX);
...
wcex.lpfnWndProc = LoadLibrary("user32", "DefWindowProcA");
...
ATOM atom = RegisterClassEx(&wcex);
However, sometimes I want to register a window class with a different window procedure. 但是,有时我想用不同的窗口过程注册一个窗口类。 In C, I would do exactly the above except: 在C语言中,除了以下内容外,我将严格执行上述操作:
wcex.lpfnWndProc = MyWindowProc; // Address of my custom window procedure
Hopefully it is now clear what the difficulty is in JNA. 希望现在清楚JNA的困难所在。 I am writing Java code similar to: 我正在编写类似于以下内容的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);
CAVEAT 警告
I am aware that I can define two alternate versions of the function f
in Java, one of which takes a Callback
and one of which takes a Pointer
, and pass my address to g
to the Pointer
version. 我知道我可以在Java中定义函数f
两个替代版本,其中一个采用Callback
而其中一个采用Pointer
,并将我的地址传递给g
到Pointer
版本。 I'm also aware that I can create a "wrapper callback" for DefWindowProcA. 我也知道我可以为DefWindowProcA创建一个“包装回调”。 For various reasons, these are not adequate solutions. 由于各种原因,这些都不是适当的解决方案。
To be able to use an external pointer as a Callback
, you type-pun the way C programmers do: with unions. 为了能够使用外部指针作为Callback
,您可以按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();
}
}
You can now read the wndProc
field and get back a usable window procedure callback. 现在,您可以读取wndProc
字段并获取可用的窗口过程回调。
For this use case, DefWindowProc
is actually exported via the User32
class, so you can just create a callback to invoke it directly: 对于此用例, 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);
}
}
Have a look at the Win32WindowDemo
class for an example of a window procedure that delegates to DefWindowProc
. 查看Win32WindowDemo
类 ,以获取委托给DefWindowProc
的窗口过程的示例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.