我正在尝试使用JNA访问我的简单DLL,该DLL是用C ++(Windows 32位,Java 8,JNA 5.2.0,Visual Studio 2017 C ++)编写的。 DLL具有创建对象的功能。而且我想获得对象上的指针,并访问JAVA代码中的对象函数。
我收到指向本地对象的JNA-Pointer,并尝试初始化它的Java结构实现。
在这里,我在JNA-Structure初始化期间遇到了异常:
public IMyClass(Pointer p) {
super(p);
线程“ main”中的异常java.lang.IllegalArgumentException:结构类edu.nyu.cpptest.cpplib.CppLibDemo $ CppLib $ IMyClass在com.sun.jna.Structure上具有未知大小或零大小(确保所有字段都是公共的)。 com.sun.jna上的.deriveLayout(Structure.java:1374).com.sun.jna上的Structure.calculateSize(Structure.java:1158).com.sun.jna上的Structure.calculateSize(Structure.java:1110)。 com.sun.jna.com的Structure.useMemory(Structure.java:350).com.sun.jna.Structure。(Structure.java:202)com.sun.jna.Structure.Structure。(Structure.java:193) 。(Structure.java:189)在edu.nyu.cpptest.cpplib.CppLibDemo $ CppLib $ IMyClass。(CppLibDemo.java:30)在edu.nyu.cpptest.cpplib.CppLibDemo。(CppLibDemo.java:52)>
C ++代码:
MyClass.h:
class __declspec(dllexport) IMyClass {
public:
//int value;
virtual int getValue() = 0;
virtual void increment() = 0;
};
class MyClass : public IMyClass {
public:
int value;
MyClass();
MyClass(int v);
int getValue();
void increment();
};
extern "C"
{
__declspec(dllexport) IMyClass* createMyClass();
};
MyClass.cpp:
MyClass::MyClass() {this->value = 0;}
MyClass::MyClass(int v) { this->value = v; }
int MyClass::getValue() { return value; }
void MyClass::increment() { value++; }
cpplib.cpp
extern "C" __declspec(dllexport) IMyClass* createMyClass() {
MyClass *mcl = new MyClass(0);
return mcl;
}
Java代码:
public class CppLibDemo {
public interface CppLib extends StdCallLibrary {
CppLib INSTANCE = Native.loadLibrary("cpplib.dll", CppLib.class);
Pointer createMyClass();
class IMyClass extends Structure {
interface Increment extends Callback {
public void invoke();
}
interface GetValue extends Callback {
public int invoke();
}
public IMyClass() { }
public IMyClass(Pointer p) {
super(p);
super.read();
}
Increment increment;
GetValue getValue;
//public int value;//I tried to add 'value' field in IMyClass-native and java code
//public void read() {
// value = (int)readField("value");
// super.read();
//}
}
}
CppLib.IMyClass myClass;
public CppLibDemo() {
Pointer ptr = CppLib.INSTANCE.createMyClass();
myClass = new CppLib.IMyClass(ptr);
}
public int getValue() {
return myClass.getValue.invoke();
}
public void increment() {
myClass.increment.invoke();
}
}
我还尝试将“值”字段从MyClass移到C ++代码中的父IMyClass,并在Java代码中的IMyClass中声明值字段。在这种情况下,我也有例外:
线程“ main”中的异常java.lang.Error:类edu.nyu.cpptest.cpplib.CppLibDemo $ CppLib $ IMyClass上的Structure.getFieldOrder()返回的名称([])与声明的字段名称不匹配([值]) 在com.sun.jna.Structure.getFields(Structure.java:1088)在com.sun.jna.Structure.deriveLayout(Structure.java:1233)在com.sun.jna.Structure.calculateSize(Structure.java:1158) )在com.sun.jna.Structure。(Structure.java:202)在com.sun.jna.Structure。(Structure.java:202)在com.sun.jna.Structure。(Structure.java:193)在com.sun.jna.Structure。(Structure.java:189)在edu.nyu.cpptest.cpplib.CppLibDemo $ CppLib $ IMyClass。(CppLibDemo.java:30)
我使用简单的控制台应用程序对此进行了测试,该应用程序将我的DLL加载到Viusual Studio中,并且运行良好。 我也可以使用SWIG java和DLL-wrapper生成器通过JNI调用DLL。有趣的是,如果JNA可以做到这一点。
答案 0 :(得分:1)
Java结构需要具有与本机结构匹配的公共字段,并且需要以正确的顺序声明这些字段。通常,您的Java代码将具有执行此操作的注释:
@Structure.FieldOrder({"value"})
public class ExampleStruct extends Structure {
public int value;
// rest of the implementation...
}