使用JNI在主机二进制文件中调用C函数

时间:2014-05-30 20:42:34

标签: java java-native-interface

我试图在托管JVM的可执行文件中调用JNI C函数。我用-rdynamic编译,并用nm -D确认符号是在动态符号表中导出的。但是,当我调用它时,JVM会抱怨找不到符号。

我过去和LuaJIT一起完成了这项工作,这是相当微不足道的,如果不能用Java完成,我会感到非常惊讶。

我在JNITest类中创建了一个测试方法

public static native int strLen();

并实施:

#include <jni.h>
#include <java/com_jnitest_JNITest.h>

#include <string>
#include <iostream>

JNIEXPORT jint JNICALL Java_com_jnitest_JNITest_strLen(JNIEnv* env, jclass clazz)
{
    return 1111;
}

int main()
{
    JNIEnv* env;
    JavaVM* jvm;

    JavaVMInitArgs args;
    JavaVMOption options[1];
    args.version = JNI_VERSION_1_8;
    args.nOptions = 1;
    args.options = options;
    args.ignoreUnrecognized = false;

    std::string classpath = "-Djava.class.path=";
    classpath += "/var/projects/jnitest/src/java";
    options[0].optionString = (char*)classpath.c_str();

    jint result = JNI_CreateJavaVM(&jvm, (void**)&env, &args);
    if (result != JNI_OK) {
        std::cerr << "Could not create JVM" << std::endl;
        return 1;
    }

    jclass main_class = env->FindClass("com/jnitest/JNITest");
    if (main_class == nullptr) {
        std::cerr << "Could not find JNITest class" << std::endl;
        return 1;
    }

    jmethodID main_method = env->GetStaticMethodID(main_class, "main", "()V");

    // Call JNITest.main() transferring control to Java
    env->CallStaticVoidMethod(main_class, main_method, nullptr);

    if(env->ExceptionCheck()) {
        env->ExceptionDescribe();
        return 1;
    }

    jvm->DestroyJavaVM();

    return 0;
}

1 个答案:

答案 0 :(得分:1)

如果加载System.loadLibrary(),JVM仅注册共享库中的所有函数。

由于您在程序中创建了JVM,它不知道这个函数,您可以使用env->RegisterNatives(...)将本机方法与您的java类链接。

此外,不需要JNIEXPORT,因为您使用函数指针注册它,并且无需从外部访问此方法。