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

标签 java winapi callback jna

我正在使用一个 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 ,并将我的地址传递给 gPointer 版本。我还知道我可以为 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/

相关文章:

JavaFX Application : is the primary stage in . start() 有什么特别的吗?

c++ - 锁定多个线程

winapi - 谁在 SetClipboardData(CF_BITMAP, HBITMAP) 中释放句柄?

vb6 - 如何在VB6中编写回调?

python - 如何在点击按钮时运行python脚本?

java - 在纯 IPv6 网络上绑定(bind)到 Java 中的 AnyLocalAddress (0.0.0.0)

java - 在 Java 中,我应该使用 ArrayList<Long> 还是 long[] ?

Java - 了解二进制形式的 image.getRGB(x,y) 输出

C# 使用自定义环境变量以管理员身份启动子进程(在 CMD 窗口中)

javascript - 重用相同的 AJAX 调用