31

したがって、Java Native Interfaceを利用するCの次のコードがありますが、これを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++と対話する違いは何ですか?どんな助けでも大歓迎です。

ありがとう、ピート

4

4 に答える 4

28

私はEssentialJNIという本を持っていました。そして、それはちょっと古いですが、それの多くは今日でも機能します。

正しく思い出せば、Cでは、Javaコンストラクトは単なるポインターです。したがって、コードでは、「(*env)->」は、基になるメソッドへのアクセスを提供するためにポインターを逆参照しています。

C ++の場合、 " env"は実際にはオブジェクトであり、Cポインタとは異なるエンティティです。(C ++は実際にオブジェクトをサポートしているため、JNIは実際にC ++コードが操作する実際のオブジェクトを提供できます。)したがって、「env->」はC ++では異なる意味を持ち、「」が指すオブジェクトに含まれるメソッドを呼び出すことを意味しますenv

もう1つの違いは、C-JNI関数の多くでは、パラメーターの1つが" JNIEnv *env"である必要があることです。したがって、Cではあなたは言わなければならないかもしれません(*env)->foo(env, bar)。C ++では、「」への2番目の参照は必要ないため、代わりに「 」envと言うことができます。env->foo(bar)

残念ながら、目の前に上記の本がないので、確認できません!しかし、これら2つのことを調査する(具体的には、Googleまたは他のJNIコードでそれらを探す)ことで、かなり遠くまで到達できると思います。

于 2009-06-01T18:41:20.193 に答える
8

CとCPPのJNI呼び出しの主な違いは、次のとおりです。

CスタイルのJNIは次のようになります(* env)-> SomeJNICall(env、param1 ...)

C++スタイルの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が2回表示されます(JNI呼び出しに適切な名前を付ける方法を常に忘れているため、JNIがすぐに機能するのはそのためです)

乾杯、私が助けてくれたらいいのに:)

于 2012-02-01T11:36:37.633 に答える
5

Cコードをでラップしてみましたかextern "C"。詳細、およびCコードをC ++で使用できるようにするその他の可能なメカニズムについては、C ++FaqLiteを参照してください。

于 2009-06-01T16:36:11.547 に答える
2

標準のC++に触れてからしばらく経ちましたが、とにかく試してみるつもりです。

(*env)->」は私には奇妙に見えます。それは単に""であるべきではありませんenv->か?

たぶん私は間違っていて、それはうまくいくはずですが、とにかく物事をもっと複雑にするのはなぜですか?

于 2009-06-01T17:41:40.373 に答える