情况:我有一个实现JNI的DLL,我想从Cpp应用程序中调用其中的方法 .
当前状态:根据我的理解,实现JNI的DLL实际上与JAVA无关,例如:在Test.java中,我写了public native int Add(int a,int b);
并通过Cpp In TestDll.Cpp实现了它JNIEXPORT jint JNICALL Java_SomeNamespace_Add(JNIEnv* _Env, jobject _Object, jint a, jint b) { return a+b; }
我认为这样的程序与JVM无关,jint结构似乎已在jni.h中完全定义 .
所以,我想知道是否可以直接调用 Java_SomeNamespace_Add
而无需从Cpp应用程序创建VM,如果可能的话,:
-
参数列表中的
JNIEnv *
和jobject
应该是什么? -
如何将
jint
变量转换为标准int
变量? -
如何在不使用
_Env-> FindClass("Ljava/lang/String;")和一堆以下代码的情况下将
jstring变量转换为标准
string`变量?
2 回答
一般来说,有一个原因可以阻止您在没有Java的情况下加载JNI DLL . DLL可能需要一些JVM外部符号 . 但如果你需要,你可以用假人伪造它们 .
如果DLL是从Java加载的,那就更容易了:你可以毫无顾虑地简单地调用DLL的任何导出函数 .
如果导出的JNI方法调用不使用JNIEnv参数(如
Add()
的示例中所示),则可以简单地传递 nullptr 以满足调用约定 .但是,这不会让您传递 jstring 或 jarray 之类的参数 . 无论如何,良好的做法是将JNI层和实际逻辑层分开,这些逻辑将从Java转换为本机的参数 .
但是如果你无法控制DLL,你可以尝试完全伪造JNI . 请参阅 jni.h 并以适合您的方式实施必要的功能 .
对于数字1,我认为使用一些重构来创建一个简单的替代方案是个好主意 .
不是将算法的逻辑放入JNI调用本身,而是将逻辑移动到单独的c函数并从两个用例中调用该函数 .
即:
对于数字2,您可以使用标准C样式转换在jint和int之间进行转换:
至于3号:
如果从JNI中调用该函数,则可以使用here描述的函数对:
要从像上面这样的C字符串转换为std :: string,您可以执行以下操作:
如果您没有使用JNI调用该函数,看起来您需要尝试滚动自己的转换 . 我会看看你是否可以使用现有的VM实现,弄清楚他们是如何做到的并模仿它 .
例如,您可以尝试以这些为起点的Android VM:https://android.googlesource.com/platform/dalvik/+/donut-release/vm/Jni.c#2230 https://android.googlesource.com/platform/dalvik.git/+/android-4.3_r3/vm/UtfString.cpp#284