Я пытаюсь получить доступ с помощью JNA к моей простой DLL, написанной на C ++ (Windows 32 bit, Java 8, JNA 5.2.0, Visual Studio 2017 C ++). У DLL есть функция, которая создает объект. И я хочу получить указатель на объект и получить доступ к объектной функции внутри JAVA-кода.
Я получаю JNA-Pointer для нативного объекта и пытаюсь инициализировать его реализацию 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.calculateSize (Structure.java:1158) на com.sun.jna.Structure.calculateSize (Structure.java:1110) на 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) в 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 в его родительский IMyClass в коде C ++ и объявить поле значения в IMyClass в коде Java. В этом случае у меня также есть исключение:
Исключение в потоке "main" java.lang.Error: Structure.getFieldOrder () для класса edu.nyu.cpptest.cpplib.CppLibDemo $ CppLib $ IMyClass возвращает имена ([]), которые не соответствуют объявленным именам полей ([[] значение])
в 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)
Я проверил это с помощью простого консольного приложения, которое загружает мою DLL в Viusual Studio и работает нормально.
И я также могу вызывать мою DLL через JNI, используя генерацию Java-оболочки и DLL-оболочки SWIG. Интересно, если это возможно с JNA.