2009-06-01 2 views
23

그래서 Java Native Interface를 사용하는 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); 
} 

자바 프로그램 :

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"); 
    } 
} 

C 및 C++와 JNI는 상호 작용의 차이는 무엇입니까? 어떤 도움이라도 대단히 감사합니다.

감사합니다, 피트

+1

도움을 희망? 그것은 유효한 C++ 코드처럼 보입니다. – jalf

+1

잘 구성된 예제로 인해 상향되었습니다. 멋지게 넣어. –

답변

19

이전에는 책이 Essential JNI이었습니다. 그리고 그것은 다소 날짜가 있지만, 오늘날 대부분은 여전히 ​​작동합니다.

C에서 올바르게 호출 한 경우 Java 구문은 단순히 포인터 일뿐입니다. 따라서 코드에서 "(*env)->"은 포인터를 역 참조하여 기본 메서드에 대한 액세스를 제공합니다.

C++의 경우 "env"은 실제로 개체 (C 포인터와 다른 개체)입니다. (실제로 C++은 객체를 지원하기 때문에 JNI는 실제로 C++ 코드를 처리 할 실제 객체를 제공 할 수 있습니다. 따라서 "env->"은 C++에서 다른 의미를 가지며 "env"이 가리키는 객체에 포함 된 메소드를 호출합니다. "

다른 차이점은 많은 C-JNI 함수가 매개 변수 중 하나가"JNIEnv *env "이어야한다는 것입니다. 따라서 C에서는 (*env)->foo(env, bar)이라고 말할 수 있습니다 .C++에서는 두 번째 참조 "env"까지는 필요하지 않으므로 대신 "env->foo(bar)"이라고 대답 할 수 있습니다.

불행히도 저는 앞에서 책을 읽지 않았기 때문에이 사실을 확실히 알 수 없습니다! 그 두 가지를 (특히 Google이나 다른 JNI 코드에서 찾고있는) 두드러지게하는 것은 당신을 상당히 멀리 할 것입니다.

+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++에서 C 코드를 사용할 수있는 다른 가능한 메커니즘에 대해서는 C++ Faq Lite을 참조하십시오.

+0

아마 그게 문제라고 생각합니다. JNI는 C 코드를 예상하므로 링크 오류가 발생했을 가능성이 높습니다. –

+0

Yarp. 이름은 아마 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를 참조 왜 그게

건배를 (내 JNI를 잘 박쥐 작동 왜 그게 내가 항상하는 방법을 제대로 JNI 호출 이름을 잊지 때문에), 나는 :) 위의 잘못은 무엇

관련 문제