从 C++ 调用 dll 实现的 JNI

Calling dll implemented JNI from C++

情况: 我有一个实现 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,如果可能的话,:

  1. 参数列表中的`JNIEnv*`和`jobject`应该是什么?
  2. 如何将 `jint` 变量转换为标准的 `int` 变量?
  3. 如何在不使用 _Env->FindClass("Ljava/lang/String;") 和以下代码的情况下将 `jstring` 变量转换为标准 `string` 变量?

一般来说,有一种原因会阻止您在没有 Java 的情况下加载 JNI DLL。 DLL 可能需要一些 JVM 外部符号。但是如果你需要的话,你可以用假人来伪造它们。

如果 DLL 是从 Java 为您加载的,那就更简单了:您可以放心地调用 DLL 的任何导出函数。

如果导出的 JNI 方法调用不使用 JNIEnv 参数(如您的 Add() 示例),您只需传递 nullptr 即可满足调用约定.

不过,这不会让您传递 jstringjarray 等参数。无论如何,好的做法是将 JNI 的层与实际逻辑分开,后者将参数从 Java 转换为本机。

但如果您无法控制 DLL,则可以尝试完全伪造 JNI。请参阅jni.h并以适合您的方式实现必要的功能。

对于第 1 点,我认为使用一些重构创建一个简单的替代方案是个好主意。

与其将算法逻辑放入 JNI 调用本身,不如将逻辑移至单独的 c++ 函数并从两个用例中调用该函数。

即:

// MyJNIWrapper.cpp
#include "MyMathFunctions.h"
JNIEXPORT jint JNICALL Java_SomeNamespace_Add(JNIEnv* _Env, jobject _Object, jint a, jint b)
{
   return (jint)add((int)a, (int)b);
}

// MyMathFunctions.h
int add(int a, int b)
{
    return a + b;
}

// MyCppProgram.cpp
#include "MyMathFunctions.h"
int main()
{
    int c = add(a, b)
}

对于数字 2,您可以使用标准 C 样式转换在 jint 和 int 之间进行转换:

int a = 10;
jint b = (jint) a;
int c = (int) b

至于数字 3:

如果您从 JNI 中调用该函数,您将使用描述的一对函数 here:

JNIEXPORT void JNICALLJava_MyJavaClass_printName(JNIEnv *env, jobject obj, jstring name)
{
    const char *str= (*env)->GetStringUTFChars(env,name,0);
    printf(“%s”, str);
    //need to release this string when done with it in order to
    //avoid memory leak
    (*env)->ReleaseStringUTFChars(env, name, str);
}

要将上述 C 字符串转换为 std::string,您可以执行以下操作:

std::string cpp_string = str;

如果您不使用 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