2015-04-25 41 views
2

我有一个C函数(编译成一个DLL),需要一个WinDef.RECT对象,并打印出的四个坐标:清分WinDef.RECT结构在JNA

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中的其他本地函数中调用),但除此之外,我有点卡住了!

+1

我注意到,当我使用一个32位JRE与32位版本的DLL时,我遇到了同样的问题,而一切正常工作与64位版本。 – regulus

+0

@regulus感谢您的观察 - 你会建议这是一个JNA错误在这种情况下? (不幸的是,我的用例将我限制为32位堆栈。) – berry120

+0

请注意,w32 API在32位系统上使用['stdcall'](http://stackoverflow.com/questions/297654/what-is-stdcall)位,但不是64位。确保你的本地库使用'stdcall',确保你的JNA映射实现了'StdCallLibrary'。 – technomage

回答

0

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

你的母语签名要求结构和您的JNA映射默认为结构*语义。更改您的原生sig或使用Structure.ByValue;除非明确需要,否则struct *是首​​选。

在我来说,我需要本地库保持不变,因此该解决方案被宣布的WinDef.RECT子类,并标记它Structure.ByValue

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

这可能则代替WinDef.RECT使用,并且似乎都没有问题。

请注意,虽然此修复程序对我来说可以正常工作,但其他人也有其他报告 - 如下面的注释中所示,切换到LPRECT是另一种可能的修复方法。

+1

在我的情况下使用ByValue没有帮助,但在我阅读你的答案后,我试着将我的方法签名更改为解决问题的LPRECT。我仍然觉得这里有一个JNA bug。 – regulus

+0

@regulus嗯,这很有趣 - 我只是尝试在64位堆栈上重新编译/运行,我实际上得到了与32位堆栈相同的结果(不管我第一次尝试的方式如何,但是使用'ByValue'修复了它。 )如果它在所有系统上似乎都不可靠工作,那么现在我很厌倦推出此代码! (无论其他人遇到同样的问题,我都会更新我的答案) – berry120

+0

请注意,您需要更改映射的函数签名*和*实际传递给标记为“Structure.ByValue”类型的对象。函数签名是决定数据如何传递给本地代码的原因,显然如果你弄错了,你可能会崩溃虚拟机,或者至多得到假数据。 – technomage