【问题标题】:Allocating WinDef.RECT struct in JNA在 JNA 中分配 WinDef.RECT 结构
【发布时间】:2015-07-03 18:45:28
【问题描述】:

我有一个 C 函数(编译成 DLL),它接受一个 WinDef.RECT 对象并打印出四个坐标:

DllExport void Test(RECT rect)
{
    printf("Rect: %i, %i, %i, %i", rect.top, rect.left, rect.bottom, rect.right);
}

在 Java (JNA) 方面,我尝试将 WinDef.RECT 传递给它,如下所示:

WinDef.RECT rect = new WinDef.RECT();
rect.bottom=0;
rect.left=0;
rect.right=0;
rect.top=0;
jna.INSTANCE.Test(rect);

但是,我只是得到了无意义的数字(这些数字不一致并且每次都不同),例如:

Rect: -857788769, 11343200, 8044544, 8044544

我假设我没有在 JNA 端正确定义 RECT(C++ 函数可以从同一个 dll 中的其他本机函数很好地调用),但除此之外我有点卡住了!

【问题讨论】:

  • 我注意到,当我将 32 位 JRE 与 32 位版本的 DLL 一起使用时,我遇到了同样的问题,而在 64 位版本上一切正常。
  • @regulus 感谢您的观察 - 在这种情况下,您会建议这是 JNA 错误吗? (不幸的是,我的用例将我限制为 32 位堆栈。)
  • 请注意 w32 API 在 32 位上使用 stdcall 调用约定,但在 64 位上不使用。确保如果您的本机库使用 stdcall,则您的 JNA 映射实现 StdCallLibrary

标签: java c++ jna


【解决方案1】:

我在 JNA 邮件列表上有一个有用的答案:

您的本机签名要求 struct 并且您的 JNA 映射默认为 struct* 语义。更改您的原生签名或使用 Structure.ByValue; struct* 是首选,除非您明确需要。

就我而言,我需要原生库保持不变,因此解决方案是声明WinDef.RECT 的子类并用Structure.ByValue 标记它:

public static class RectByValue extends WinDef.RECT implements Structure.ByValue {}

然后可以用它代替WinDef.RECT,一切似乎都没有问题。

请注意,虽然此修复对我来说没问题,但其他人已经报告了其他情况 - 如下评论所示,将类型切换为 LPRECT 是另一个潜在的修复。

【讨论】:

  • 在我的情况下,使用 ByValue 并没有帮助,但是在阅读了您的答案后,我尝试将方法签名更改为 LPRECT,从而解决了问题。我仍然觉得这里有一个 JNA 错误。
  • @regulus 嗯,这很有趣 - 我只是尝试在 64 位堆栈上重新编译/运行,实际上我得到了与 32 位堆栈相同的结果(我第一次尝试时不起作用,但是使用ByValue 修复了它。)如果它似乎不能在所有系统上可靠地工作,我现在厌倦了推出这段代码! (如果其他人遇到同样的问题,我会用你的评论更新我的答案。)
  • 请注意,您需要同时更改映射函数签名 实际上传入一个带有 Structure.ByValue 类型标记的对象。函数签名决定了数据如何传递到本机代码,显然,如果你弄错了,你可能会导致 VM 崩溃或充其量是获取虚假数据。
猜你喜欢
  • 1970-01-01
  • 2012-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多