Вызовы JNI разные в C против C ++? - PullRequest
30 голосов
/ 01 июня 2009

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

 #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 и C ++? Любая помощь с благодарностью.

Спасибо, Пит

Ответы [ 5 ]

25 голосов
/ 01 июня 2009

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

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

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

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

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

6 голосов
/ 01 февраля 2012

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

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

JNI в стиле C ++ выглядит 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)

Ура, надеюсь, я помог:)

5 голосов
/ 01 июня 2009

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

2 голосов
/ 01 июня 2009

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

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

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

0 голосов
/ 01 июня 2009

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...