【发布时间】:2019-01-21 21:45:53
【问题描述】:
我正在尝试使用 JNA 访问我用 C++(Windows 32 位、Java 8、JNA 5.2.0、Visual Studio 2017 C++)编写的简单 DLL。 DLL 具有创建对象的功能。我想获取对象上的指针并访问 JAVA 代码中的对象函数。
我收到指向本机对象的 JNA-Pointer 并尝试初始化它的 Java-Structure 实现。
在这里我在 JNA-Structure 初始化期间有异常:
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.calculateSize(Structure.java:1158) 在 com.sun.jna.Structure.calculateSize(Structure.java:1110) 在 com.sun.jna。 Structure.useMemory(Structure.java:350) at com.sun.jna.Structure.(Structure.java:202) at com.sun.jna.Structure.(Structure.java:193) at com.sun.jna.Structure .(Structure.java:189) at edu.nyu.cpptest.cpplib.CppLibDemo$CppLib$IMyClass.(CppLibDemo.java:30) at 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();
}
}
我还尝试在 C++ 代码中将“值”字段从 MyClass 移动到它的父 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.useMemory(Structure.java:350) 在 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)
我使用简单的控制台应用程序对此进行了测试,该应用程序在 Viusual Studio 中加载了我的 DLL,并且运行良好。 而且我还可以使用 SWIG java & DLL-wrapper 生成通过 JNI 调用我的 DLL。有趣的是,如果 JNA 可以做到这一点。
【问题讨论】:
-
JNA 不支持 C++,试试 JavaCPP:github.com/bytedeco/javacpp