Hello JNI (3), C 라이브러리에 문자열 전달
From Evernote: |
Hello JNI, C 라이브러리에 문자열 전달 |
이전 글에서 작성한 Hello Jni 프로젝트를 다시 한 번 더 수정해서, 이번에는 C 라이브러리 쪽으로 문자열을 전달하고, C에서는 전달받은 문자열을 화면에 출력하도록 작성한다.
다음과 같이 자바 소스 파일에 네이티브 메서드를 하나 추가한다.
package kr.pe.elex.example.jni;
/**
* JNI 테스트
*
* @version 3
* @author Elex
*/
public class HelloJni {
static {
System. loadLibrary("libhellojni");
}
/**
* C 언어에서 한 줄 출력한다.
*/
private native void printOut();
/**
* C 언어에서 문자열을 전달 받는다.
*
* @return
*/
private native String getStringFromC();
/**
* C 언어에 문자열을 전달하고, C에서는 전달받은 문자열을 출력한다.
*
* @param str
*/
private native void putStringToC(String str);
public static void main(String[] args) {
HelloJni test = new HelloJni();
// test.printOut();
//System.out.println(test.getStringFromC());
test.putStringToC( "Hello Jni to C");
}
}
#. putStringToC()라는 네이티브 메서드를 추가했다. 이 메서드는 매개변수로 String을 전달 받는다.
#. 그리고, 새로 추가한 메서드가 실행되도록 메인 메서드를 조금 수정했다.
#. 새로 생성된 자바 클래스 파일로부터 javah 도구를 사용해서 헤더 파일을 추출하면 아래와 같다. (함수명 앞에 밑줄문자를 추가해 준다.)
/*
* Class: kr_pe_elex_example_jni_HelloJni
* Method: putStringToC
* Signature: ( Ljava/lang /String;)V
*/
JNIEXPORT void JNICALL
_Java_kr_pe_elex_example_jni_HelloJni_putStringToC(JNIEnv *, jobject, jstring);
#. 자바로부터 전달은 매개변수가 세 번째 인자로 추가된 것을 확인할 수 있다. jstring 타입이다.
헤더 파일에 정의된 함수 원형을 기초로 C 소스 파일에 새로운 함수를 구현하면, 아래와 같다. 이전 프로젝트에서 맨 마지막 함수만 새로 추가되었다.
/*
* hellojni.c
* JNI 테스트를 위한 C 라이브러리
* Author: Elex
*/
#include "kr_pe_elex_example_jni_HelloJni.h"
JNIEXPORT void JNICALL
_Java_kr_pe_elex_example_jni_HelloJni_printOut (JNIEnv *env, jobject obj)
{
puts( "Hello Jni !");
}
JNIEXPORT jstring JNICALL
_Java_kr_pe_elex_example_jni_HelloJni_getStringFromC( JNIEnv *env, jobject obj)
{
return (*env)-> NewStringUTF(env, "Hello Jni from C!");
}
JNIEXPORT void JNICALL
_Java_kr_pe_elex_example_jni_HelloJni_putStringToC (JNIEnv *env, jobject obj,
jstring str)
{
const char* s;
s = (*env)->GetStringUTFChars(env, str, NULL);
if (s != NULL)
{
printf( "%s", s);
}
(*env)->ReleaseStringUTFChars(env, str, s);
}
#. jstring 타입은 C언어의 문자열과 다르므로, printf(%s, str)이라고 사용할 수는 없다. jstring 타입을 C 언어의 문자열 표현으로 변환해야 한다.
#. JNIEnv 인터페이스 포인터를 통해서 GetStringUTFChars() 함수를 사용하면 jstring 형식으로부터 UTF8 형식의 문자열로 변환할 수 있다.
#. GetStringUTFChars() 함수의 세 번째 매개변수 jboolean *isCopy를 통해 jstring 문자열이 java.lang.String 인스턴스의 사본인지 아닌지를 전달 받는다. JNI_TRUE 또는 JNI_FALSE이다. 만일, JNI_FALSE인 때에는 네이티브 코드에서 해당 문자열을 수정해서는 안된다. (대부분의 경우 확인할 필요가 없으니 NULL을 주면 된다고 한다.)
#. 간혹 메모리 할당이 실패할 경우도 있으므로 GetStringUTFChars()의 리턴 값이 NULL인지 확인 해야한다. NULL인 때에는 OutOfMemoryError가 던져질 것이다.
#. GetStringUTFChars()로 가져온 문자열의 사용이 끝났다면 ReleaseStringUTFChars()를 사용해서 메모리를 놓아주어야 한다. 그렇지 않으면 메모리 누수가 발생할지도 모른다. ReleaseStringUTFChars()는 자바의 가비지 콜렉터에게 수집되어도 괜찮다는 의사표시라고 볼 수 있다.
#. NewStringUTF(), GetStringUTFChars(), ReleaseStringUTFChars()와 유사한 NewString(), GetStringChars(), ReleaseStringChars() 함수들도 있는데, 전자들은 UTF-8 인코딩으로 문자열로 처리하는 반면, 후자들은 유니코드 인코딩으로 문자열을 처리한다. 후자의 경우 문자열 끝에 널문자가 포함되지 않는다.
#. 또한, 문자열의 길이를 확인하기 위해 GetStringLength(), GetStringUTFLength() 함수를 사용할 수도 있다.
<프로젝트 파일>
http://www.elex.pe.kr/attachment/cfile23.uf@2204424F522F4591353E3C.7z
<프로젝트 파일>
http://www.elex.pe.kr/attachment/cfile23.uf@2204424F522F4591353E3C.7z
댓글
댓글 쓰기