简体   繁体   English

在JNA定义需要回调的地方传递原始函数指针?

[英]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 ,并将我的地址传递给gPointer版本。 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM