2009-06-01 12 views
23

私はJavaネイティブインターフェイスを使用してCでこれをC + +に変換したいのですが、どのように確かではないC言語で次のコードがあります。JNI 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++と相互作用するの違いは何ですか?どんな助けでも大歓迎です。

ありがとう、Pete

+1

を助け願っていますか?私には有効なC++コードのようです。 – jalf

+1

うまく構築された例のために上書きされました。うまく置く。 –

答えて

19

私は以前本を持っていましたEssential JNI。それはまあまあですが、今日のそれはまだまだです。

私が正しく思い出したのは、C言語では、Javaの構造体は単にポインタに過ぎません。したがって、あなたのコードでは、 "(*env)->"はポインタを逆参照して、基になるメソッドにアクセスできるようにします。

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

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

残念ながら、私は前の本を私の目の前に持っていないので、私はこれを確かめることはできません! (Googleや他のJNIコードで具体的に探している)これらの2つのものを掘り下げることは、あなたをかなり遠くにさせるでしょう。

+0

JNIはCとC++の両方を実際に扱うことができますか?私はそれを知らなかった(しかし、JNIを使​​ったことはないので、それは驚くことではないかもしれない:p)。 –

+0

(私のマークダウンを修正するためのハハ、タイ!) インタフェースは同じように動作します.CとC++のコードは/基本的に/同形であり、実際には唯一の違いは構文です。 – poundifdef

-1

最初のコードは正しいC++ですか?だから、あなたは終わった!

真剣に、あなたはそのコードで何を変更したいですか?どうして?

+0

私は上記のコードを.cとしてコンパイルするとうまく動作し、うまく動作します.cppに変更するとエラーが発生します –

+0

それで、エラーを投稿して、私たちは何を答えているのか分かりますか? ;) – jalf

+0

彼が投稿したコードはCコードで、JNI + Cにはポインタが必要です。しかし、JavaとC++をリンクするとき、JNIは "オブジェクトのように振る舞う構造体へのポインタ"ではなく、/ objects/- を母国語に提供します。 – poundifdef

5

extern "C"でCコードをラップしてみましたか?詳細は、C++ Faq Liteを参照してください。C++でCコードを使用できるようにするための他のメカニズムもあります。

+0

おそらくそれは問題だと思います。 JNIはCコードを期待しているので、おそらくリンクエラーが発生しています。 Yarp。 –

+0

。おそらくC++コンパイラでは名前が混乱しています。 extern C {}を追加します。 – Kieveli

2

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

(*env)->」は私には奇妙に見えます。単純に「env->」ではありませんか?

多分私は間違っていて、うまくいくはずですが、どうしても複雑なものにするのはなぜですか?

+3

x-> yは(* x).yの短縮形です。したがって、(* env) - > yは(** env).yと等価です。これは(* env)と異なります.y:余分な参照が発生します。 –

+0

逆参照の構文は、私は実際に知っていた。もっと明確にする:JNIEnvのC++バージョンが実際に二重逆参照を必要としていると確信しているにすぎない。 –

4

JNIの主な違いは、Cに呼び出し、CPPはこれです:

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_(パッケージ名)_(クラス名)_(methodNameの)

であることがわかります

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を参照してくださいThatsなぜ

乾杯(と私のJNIは、右のバット作品Thatsなぜ私はいつもどのように適切にJNI呼び出しの名前を忘れているため)、私は:)上記と間違って何

関連する問題