JNA从DLL调用C++对象-java.lang.IollegalArgumentException:Structure



我正试图用JNA访问我在C++(Windows 32位,Java 8,JNA 5.2.0,Visual Studio 2017 C++)上编写的简单DLL。DLL具有创建对象的功能。我想得到对象上的指针,并访问JAVA代码中的对象函数
我收到指向本机对象的JNA指针,并尝试初始化它的Java结构实现
这里我在JNA结构初始化期间出现异常:

public IMyClass(Pointer p) { 
super(p); 

线程"main"java.lang.IllegalArgumentException中的异常:结构类edu.nyu.cpptest.cpplib.CppLibDemo$cpplib$IMyClass在com.sun.jna.Structure.deriveLayout(Structure.java:1374)的com.sun.jna.Structure.caculateSize(Structure.java:1158)在com.sun.jna.Structure.caculatesizecom.sun.jna.Structure.useMemory(Structure.java:350)在com.sun.jna.Structure.(Structure.java:202)在com.sun.jna.Sstructure.(Structure.java:193)在edu.nyu.cpptest.cpplib.CppLibDemo$cpplib$IMyClass

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();
}
}

我还尝试在C++代码中将"value"字段从MyClass移到它的父IMyClass,并在Java代码中在IMyClass中声明value字段。在这种情况下,我也有例外:

线程"main"java.lang.Error:类edu.nyu.cpptest.cpplib.CppLibDemo$cpplib$IMyClass返回与声明字段名([value])不匹配的名称([])在com.sun.jna.Structure.getFields(Structure.java:1088)在com.sun.jna.Structure.deriveLayout(Structure.java:1233)在com.sun.jna.Structure.caculateSize(Structure.jjava:1158edu.nyu.cpptest.cpplib.CppLibDemo$cpplib$IMyClass.(CppLibDemo.java:30)

我用简单的控制台应用程序测试了这一点,该应用程序在Vicommon Studio中加载了我的DLL,它运行良好。我还可以使用SWIG java&DLL包装生成。如果JNA能做到这一点的话,这很有趣。

Java结构需要具有与本机结构匹配的公共字段,并且需要以正确的顺序声明这些字段。通常,您的Java代码会有一个这样做的注释:

@Structure.FieldOrder({"value"})
public class ExampleStruct extends Structure {
public int value;
// rest of the implementation...
}

相关内容

最新更新