1
votes

Situation: I have a dll which implemented JNI,I want to call the methods in it from a Cpp application.

Current Status: According to my understanding, a dll which implemented JNI actually has nothing to do with JAVA, for example: In Test.java, I wrote
public native int Add(int a,int b);
And realized it with Cpp In TestDll.Cpp
JNIEXPORT jint JNICALL Java_SomeNamespace_Add(JNIEnv* _Env, jobject _Object, jint a, jint b) { return a+b; }
I think that such a program has nothing to do with JVM, the jint structure seems have been fully defined in jni.h.
So, I wonder if it's possible to call Java_SomeNamespace_Add directly without creating a VM from a Cpp application, if it do is possible,:

  1. What should the `JNIEnv*` and the `jobject` in the parameter list be?
  2. How can i convert a `jint` variable to a standard `int` variable?
  3. How can i convert a `jstring` variable to a standard `string` variable without using `_Env->FindClass("Ljava/lang/String;")` and a bunch of following code?
2
1. They would be null. 2. jint and int32_t is the same thing. 3. jstring cannot be converted to std::string without Java JNI code.. You can create a JVM using JNI and then do the conversion..Brandon
@Brandon Can I just include jni.h and do something then it magically works?Ragnarokkr Xia
Did you verify that your actual DLL doesn't do anything with the env pointer and/or the receiver object or possible parameter objects? I don't think you can generalize this from your test function.user2543253

2 Answers

1
votes

For number 1 I think it would be a good idea to just create a simple alternative using a bit of refactoring.

Instead of putting the logic of the algorithm into the JNI call itself, move the logic to a separate c++ function and invoke that function from both use cases.

ie:

// 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)
}

For number 2, you can convert between jint and int using standard C style casts:

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

As for number 3:

If you are calling the function from within JNI, you would use the pair of functions described 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);
}

To convert from a C string like above to std::string you can do the following:

std::string cpp_string = str;

If you are not calling the function using JNI, it looks like you will need to try and roll your own conversion. I would see if you can use an existing VM implementation, figure out how they do it and mimic that.

For example you could try the Android VM with these as a starting point: 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

1
votes

Generally speaking, there is one cause that can prevent you to load a JNI DLL without Java. The DLL may need some JVM external symbols. But you can fake them with dummies, if you need.

If the DLL is loaded from Java for you, it's even easier: you can simply call any exported function of the DLL without fear.

If an exported JNI method call does not use the JNIEnv parameter (as in your example of Add()), you can simply pass nullptr to satisfy the calling convention.

This won't let you pass parameters like jstring or jarray, though. The good practice, in any case, is to separate the layers of JNI and the actual logic, which takes parameters converted from Java to native.

But if you have no control of the DLL, you can try to fake the JNI altogether. See jni.h and implement the necessary functions the way that suits you.