Используйте JNI для вызова функций C в двоичном хосте

1

Я пытаюсь вызвать функцию JNI C в исполняемом файле, на котором размещена JVM. Я скомпилирован с -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;
}
  • 0
    Во-первых, Java это не Lua. Во-вторых, вы можете предпочесть JNA (я знаю, что мне легче).
  • 0
    Проще, да, но мне все равно нужен JNI для некоторых функций из соображений производительности.
Показать ещё 1 комментарий
Теги:
jni

1 ответ

1
Лучший ответ

JVM регистрирует все функции внутри общей библиотеки, если загружается System.loadLibrary().

Поскольку вы создаете JVM внутри своей программы, он не знает об этой функции, вы можете использовать env-> RegisterNatives (...) для связывания собственных методов с вашим классом java.

Также JNIEXPORT не требуется, потому что вы регистрируете его с помощью указателя на функцию, и нет необходимости делать этот метод доступным извне.

  • 0
    Я думал, что оставил комментарий здесь. Спасибо, это решило мою проблему отлично, и это намного менее противно, чем джава и искаженные имена. Я не смог обнаружить, есть ли разница в производительности, но поскольку динамическое связывание по сути работает и на указателях функций, я не могу представить, чтобы этот подход был медленнее.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню