Подтвердить что ты не робот

JNI Вызывает разные в C vs С++?

Итак, у меня есть следующий код в C, который использует Java Native Interface, но я хотел бы преобразовать его в С++, но не уверен, как это сделать.

 #include <jni.h>
 #include <stdio.h>
 #include "InstanceMethodCall.h"

 JNIEXPORT void JNICALL 
 Java_InstanceMethodCall_nativeMethod(JNIEnv *env, jobject obj)
 {
     jclass cls = (*env)->GetObjectClass(env, obj);
     jmethodID mid = (*env)->GetMethodID(env, cls, "callback", "()V");
     if (mid == NULL) {
         return; /* method not found */
     }
     printf("In C\n");
     (*env)->CallVoidMethod(env, obj, mid);
 }

Программа Java:

 class InstanceMethodCall {
     private native void nativeMethod();
     private void callback() {
         System.out.println("In Java");
     }
     public static void main(String args[]) {
         InstanceMethodCall c = new InstanceMethodCall();
         c.nativeMethod();
     }
     static {
         System.loadLibrary("InstanceMethodCall");
     }
 }

В чем различия, с которыми JNI взаимодействует с C и С++? Любая помощь приветствуется.

Спасибо, Пит

4b9b3361

Ответ 1

Раньше у меня была книга Essential JNI. И хотя это отчасти датировано, многие из них все еще работают сегодня.

Если я правильно помню, в C конструкторы Java являются просто указателями. Таким образом, в вашем коде "(*env)->" является указателем разыменования, чтобы предоставить вам доступ к основным методам.

Для С++ "env" на самом деле является объектом - другой сущностью, чем C-указатель. (И JNI может фактически предоставлять реальные объекты для вашего кода на С++ для управления, поскольку С++ фактически поддерживает объекты.) Поэтому "env->" имеет другое значение в С++, это означает "вызвать метод, содержащийся в объекте, на который указывает "env".

Другим отличием, я считаю, является то, что многие из функций C-JNI требуют, чтобы одним из ваших параметров был "JNIEnv *env". Итак, в C вам, возможно, придется сказать (*env)->foo(env, bar). С С++ вторая ссылка на "env" не нужна, поэтому вы можете вместо этого сказать "env->foo(bar)"

К сожалению, у меня нет вышеупомянутой книги передо мной, поэтому я не могу это подтвердить! Но я думаю, что исследование этих двух вещей (особенно их поиск в google или в другом коде JNI) доставит вам довольно далеко.

Ответ 2

Вы пробовали обернуть свой код C в extern "C". См. С++ Faq Lite для получения дополнительной информации и для других возможных механизмов, позволяющих использовать ваш C-код с С++.

Ответ 3

Основное различие между вызовами JNI в C и CPP заключается в следующем:

C-стиль JNI выглядит (* env) → SomeJNICall (env, param1...)

Стиль С++ JNI выглядит так: env- > SomeJNICall (param1...)

чтобы преобразовать его в CPP, вам нужно сделать

Java_InstanceMethodCall_nativeMethod(JNIEnv *env, jobject obj)
{
    jclass cls = env->GetObjectClass(obj);
    jmethodID mid = env->GetMethodID(cls, "callback", "()V");
    if (mid == NULL) {
        return; /* method not found */
}
printf("In C++\n");
env->CallVoidMethod(obj, mid);
//rest of your code

Кроме того, убедитесь, что ваши функции JNI соблюдают соглашение об именах.

Пример:

JNIEXPORT jint JNICALL Java_com_shark_JNITestLib_JNITestLib_startServer(JNIEnv* env, jobject o, jstring inputName, jstring streamName, jstring description) {

Вы можете видеть, что соглашение Java_ (имя пакета) _ (имя_файла) _ (имя метода)

так как вышеприведенное было использовано в классе, таком как

package com.shark.JNITestLib

import java.util.stuff;

public class JNITestLib 
{
    static
    {
        System.loadLibrary("myJNIlib");
    }

    public native synchronized int startServer(String inputName, String streamName, String description);

//more class stuff...
}

При работе с JNI я сделал соглашение, чтобы назвать класс, содержащий вызовы JNI, тем же именем, что и пакет. Вот почему вы дважды видите JNITestLib (и поэтому мой JNI работает сразу с места в карьер, потому что я всегда забываю, как правильно назвать вызовы JNI)

Привет, надеюсь, я помог:)

Ответ 4

Прошло некоторое время с тех пор, как я коснулся стандартного С++, но я все равно попробую.

"(*env)->" выглядит странно для меня. Разве это не должно быть "env->"?

Возможно, я ошибаюсь, и это должно сработать, но зачем все это усложнять?

Ответ 5

Первый код - правильный С++, не так ли? Итак, все готово!

Серьезно, что вы хотите изменить в этом коде? Почему?