我有一个调用我的c ++代码的本机函数调用,这段代码创建了一个用户定义类的实例。
此功能具有以下签名:
public native Object loadEngine(int arg);
在完成此调用之后,我想调用更多本机函数,这些函数将从loadEngine()返回“Object”并对其进行修改或从中请求数据。
签名的一个例子:
public native String loadEngine(Object engine, int queryID);
以下场景会生成一个错误,说它无法将GameEngine转换为jobject,这是可以理解的,但这是我最好的镜头,对Java的经验非常少:
JNIEXPORT jobject JNICALL Java_package_loadEngine
(JNIEnv *env, jobject obj, jint arg) {
GameEngine engine(params);
return (jobject)engine;
}
JNIEXPORT jstring JNICALL Java_package_queryAction
(JNIEnv *env, jobject obj, jobject engine, jint arg) {
String ret = newString(Integer.toString((GameEngine)engine.unimportant()));
return ret;
}
由于我通过jni调用本机java代码到c ++,我不幸地无法将原生函数定义为:
public native GameEngine loadEngine(int arg);
可以理解,但我似乎无法找到解决方法。
谢谢,Scarlet。
答案 0 :(得分:4)
您可以创建包含,拥有和管理本机代码的Java包装器类。例如(在我脑海中,大脑编译):
class GameEngine {
private long nativeGameEnginePointer;
private native long loadEngine();
public GameEngine() {
super(...);
nativeGameEnginePointer = loadEngine();
}
private native void destroyEngine(long nativePointer);
protected void finalize() throws Throwable {
try {
destroyEngine(nativeGameEnginePointer);
} finally {
super.finalize();
}
}
private native double nativePlayGameOrWhatever(long nativePointer);
public double playGameOrWhatever() {
return nativePlayGameOrWhatever(nativeGameEnginePointer);
}
}
在你的JNI实施中:
class CxxGameEngine;
JNIEXPORT jlong JNICALL GameEngine_loadEngine(JNIEnv *env, jobject obj) {
return (jlong)(new CxxGameEngine(params));
}
JNIEXPORT jvoid JNICALL GameEngine_destroyEngine(JNIEnv *env, jobject obj, jlong nativePointer) {
delete (CxxGameEngine *)nativePointer;
}
JNIEXPORT jdouble JNICALL GameEngine_nativePlayGameOrWhatever(JNIEnv *env, jobject obj, jlong nativePointer) {
return ((CxxGameEngine *)nativePointer)->playGameOrWhatever();
}
请注意使用long
来表示本机指针。这就是Java运行时在需要时(例如在java.nio
和java.util.zip
包中)这样做的方式。)long
而不是int
确保类型足够宽以容纳指针甚至在64位系统上。