<JNI>자바에서 c언어 사용하기

 

자바의 제약사항

자바는 운영체제에 독립적이기 위하여 자바가상머신을 이용한다. 이는 운영체제에 독립적이라는 편의성을 제공하지만, 한편으론 운영체제에서 사용할 수 있는 모든 기능을 끌어와 쓸 수 없다는 단점이 존재한다. 또한 자바는 바이트 코드로 된 프로그램이기 때문에 c나 c++등의 프로그램으로 만들어진 기계어 코드에는 속도가 느릴 수 밖에 없다.

 

자바의 제약사항을 덜어주는 JNI란?

JNI는 자바 이외의 언어로 작성된 프로그램을 JVM 위에서 실행 할 수 있도록 인터페이스를 제공해 주는 것이다. 따라서 JNI를 활용하면, 자바에서는 일부분의 제약이 있었던 운영체제만의 좋은 기능을 활용 할 수 있을 뿐만이 아니라, 여러 시스템을 아우를 수 있다.

 

 

 

 

 

 

이클립스에서 java JNI 로 dll 로드를 시켜보자.

 

자바 JNI 의 원리는 다음과 같다.

1. 자바 소스 내에서 호출하려는 C함수에 대한 선언과 호출구문 dll 로드문을 작성한다.

2. native call 하려는 C함수에 대한 정의문 및 헤더파일을 작성한다.

3. 만들어진 C파일을 dll 빌드한다.

4. 빌드된 dll 을 자바에서 사용한다.

 

C에서 dll 로드를 시킬 때와 비슷한 구조를 보인다.

( C에서는 LoadLibrary(), GetProcAddress() 순으로 )

 

 

자바에서 system("cls"); 를 호출해보도록 하자.

 

시스템 함수를 호출 하다 보니 os에 종속적이게 되고,

java만의 각 플렛폼 별 호환성은 떨어지게 된다.

(dll 만 플렛폼에 맞추면 동작할 것 같기도 하다.)

 

 

 

먼저 아래와 같이 JNI 호출을 위한 코드를 작성해주자.

(호출할 함수 선언 및 dll 을 로드한다.)

 

위에서 함수 이름은 C로 작성한 dll 의 함수 이름이다.

static 으로 빼둔 건 loadLibrary 를 함수하기 위해도 있고,

객체 생성 할 때 마다 로드 할 필요가 없기 때문이다.

 

함수 호출 시엔 class 생성 후 인스턴스.함수이름() 으로 호출하면 된다.

단 한번의 호출이라면

new ClassName().함수이름();

( gc에 의해 알아서 객체를 해제한다. )

 

이클립스에선 저장만 해도 컴파일이 되기 때문에

경로의 bin/패키지명/ 으로 가게되면 class 파일이 생성되어 있다.

(만약 없으면 javac 로 소스를 컴파일 해줘야 한다.)

 

 

 

자바 헤더파일을 작성하자.

c 코드 작성 전 먼저 jni 헤더파일을 생성해줘야 한다.

이 때 javah 의 대상은 java 소스로 컴파일한 바이트 코드( 클래스명.class ) 이다.

javah bin/패키지명/ 에서 수행하도록 한다.

javah 패키지명.클래스명

 

헤더 파일이 만들어 진다면 jni_클래스명.h 파일이 생성된다.

 

Error : Could not find class file for 'HelloWorld'.

에러 발생 시 다음을 참고하자

( 클릭 )

 

 

다음은 dll 파일의 c코드 작성이다.

 

아까 만든 javah 파일을 열어서 확인해보면,

다음과 같이 작성되어 있는데 저 헤더를 그대로 가져와 사용해도 되며

필자는 빨간색으로 쳐진 함수 이름만 가져와 사용하도록 하겠다.

 

jni.h 파일을 include 하였고, 그 후 필요한 헤더들을 넣었다.

3 라인의 KOKW_Game_Config.h 같은 경우는 필자의 패키지명_클래스명.h 로 아까 만든 javah 파일의 이름이다.

 

그 후 함수선언 후에 필요한 구문을 작성한다.

함수 명의 경우는

 

JNIEXPORT void JNICALL Java_패키지명_클래스명_함수명(JNIEnv *, jobject)

 

빨간 부분만 변하는 것 같으며, 자바소스에서 선언해 둔 native 함수들마다 각각 정의를 해주면 될 것 같다.

(함수명이나 리턴형식 등 함수의 기본구조는 무시하면 동작을 하지 않는다.)

 

 

마지막 dll 을 생성할 차례이다.

보통 일반적으로 사용하는 vs 컴파일러의 경우

jni.h 파일과 아까 javah 로 생성한 헤더파일의 경로를 지정해줘야 한다.

그 후 추가 디렉터리 설정으로 jdk 위치를 잡아줘야 한다.

경로는 두가지를 설정해주도록 하는데 다음과 같다.


1. jdk설치경로\include

2. jdk설치경로\include\win32

 

그 후 소스를 보자.

 

이대로 컴파일을 하면 Java 에서 사용 가능한 dll 파일이 컴파일 된다.

 

 

 

 

 

다음으론 cl 컴파일러를 이용한 컴파일 방법에 대해 알아보도록 하겠다.

 

원하는 컴파일 비트의 도구를 실행한다.

(관리자 권한으로 실행해야 속 편하다.)

 

실행 후 "cl" 이란 명령어를 쳐보자.

 

cl 컴파일러가 정상적으로 실행된다.

 

그럼 dll을 빌드해보도록 하자.

 

cl –I "C:\jdk경로\include" –I"C:\jdk경로\include\win32" –LD "c소스 파일 위치" –FeDLL명.dll

 

빨간색 부분은 사용자마다 가변적인 부분이다.

각자 맞춰서 인자를 바꿔서 사용하도록 하자.

 

-I (대문자 'i') 옵션은 include 할 파일들의 디렉터리를 지정한다.

-LD 옵션은 dll 파일 생성 시 추가한다.

-Fe 옵션은 실행파일의 이름을 지정한 이름으로 바꿀 때 사용한다.

 

-I 옵션의 경우 띄어쓰기를 해도 되지만,

-Fe 옵션의 경우 띄어쓰기를 하지 않는게 맞는 명령어 이다.

 

 

마지막으로 dll 파일은 프로젝트의 루트경로에 복사해 두면

 

자바 내에서 dll 함수를 제대로 임포트하여 호출이 가능해진다.

+ Recent posts