传递一个原始函数指针,JNA定义需要一个回调?

时间:2014-07-06 03:16:03

标签: java winapi callback jna

我正在使用期望Callback的JNA接口。我有一个本机函数g的原始地址,这是我想要作为回调安装的函数。我正在调用本机函数f,它需要一个回调,我希望JNA将我的原始指针编组为g作为回调,只需将g的地址传递给{{ 1}}。这可能与JNA有关吗?

例证

这是我的意思的具体例证。我正在使用Win32,我想注册一个窗口类,其默认窗口过程为f。在普通课程中,我将在C中执行以下操作以注册具有默认窗口过程的窗口类:

DefWindowProc

但是,有时我想注册一个具有不同窗口过程的窗口类。在C中,除了:

之外,我会做到以上所述
WNDCLASSEX wcex;
ZeroMemory(&wcex, sizeof(WNDCLASSEX));
wcex.cbSize = sizeof(WNDCLASSEX);
...
wcex.lpfnWndProc = LoadLibrary("user32", "DefWindowProcA");
...
ATOM atom = RegisterClassEx(&wcex);

希望现在很清楚JNA的难点在于什么。我正在编写类似于:

的Java代码
wcex.lpfnWndProc = MyWindowProc; // Address of my custom window procedure

CAVEAT

我知道我可以在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); 的两个备用版本,其中一个版本需要f,其中一个版本需要Callback,并传递我的地址到Pointerg版本。我也知道我可以为DefWindowProcA创建一个“包装器回调”。由于各种原因,这些都不是充分的解决方案。

1 个答案:

答案 0 :(得分:1)

为了能够将外部指针用作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();
    }
}

您现在可以阅读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,了解委托给DefWindowProc的窗口过程示例。