본문 바로가기
프로그래밍/Android

자바에서 C 라이브러리 함수 호출하기

by 이재만박사 2017. 12. 19.

예제 프로그램 - C 함수를 호출하는 간단한 자바 프로그램


자바에서 호출할 C 함수는 콘솔 화면에 문자열을 출력하는 간단한 함수다


예제 프로그램에서 자바가 JNI를 통해 어떻게 C 함수를 호출하는지에 초점을 맞춰 살펴보기 바란다


여기서 보여줄 예제는 이해하기 어렵지 않으며 JNI를 이용해서 개발할 때는 대부분 동일한 절차를 밟으므로 이번 예제를 통해 확실히 이해해두기 바란다



전체적인 개발 순서


자바에서 JNI를 거쳐 C 함수를 호출하려면 다음과 같이 진행해야 한다


1단계. 자바 코드 작성


2단계. 자바 코드 컴파일


3단계. C 헤더 파일 생성


4단계. C 코드 작성


5단계. C 공유 라이브러리 생성


6단계. 자바 프로그램 실행




1단계. 자바 코드 작성


예제와 같이 자바 코드에서 JNI 를 통해 C로 구현된 함수를 호출하려면 단순히 자바 클래스에 네이티브 메서드를 선언하기만 하면 된다


네이티브 메서드란 자바 메서드이긴 하지만 실제로 자바가 아닌 C/C++ 같은 네이티브 언어로 작성된 함수를 말한다


자바쪽 선언 메서드 - 네이티브 메서드

C/C++ 코드 - JNI 네이티브 함수


// HelloJNI.java


public class HelloJNI {

// Declare native method

native void printHello();

native void printString(String str);  // 1

// Loading library

static {

System.loadLibrary("hellojni);   // 2

}


public static void main(String args[]){

HelloJNI jni = new HelloJNI();

// Call native method (Actually, called JNI native function implemented by C

jni.printHello();  // 3

jni.printString("Hello World from printString fun");

}

}




1. 자바 클래스에서는 C/C++로 작성된 네이티브 함수와 연결할 메서드를 native 키워드를 이용해서 선언한다


native 키워드는 자바 컴파일러에게 이 키워드가 선언된 메서드는 실제 자바가 아닌 외부의 다른 언어(이를 테면, C/C++)로 구현돼 있음을 알려주는 역할을 한다


따라서 HelloJNI 클래스에서 native로 선언된 printHello() 와 printString() 메서드는 자바로 작성된 구현부가 없다


만약 메서드에서 native 키워드를 생략하면 어떻게 될까? 당연히 자바 컴파일러는 printHello() 메서드의 구현부가 없다며 컴파일 오류를 출력할 것이다



2. 네이티브 메서드가 실제로 구현돼 있는 C 라이브러리를 System.loadLibrary() 메서드를 호출해서 로딩한다

System.loadLibrary() 메서드는 인자로 넘긴 문자열에 해당하는 네이티브 라이브러리를 로딩하며, 

윈도우에서는 다음 라이브러리가 로딩된다


System.loadLibrary("hellojni") 를 호출했을 때 hellojni.dll 을 로딩하게 된다


일반적으로 자바에서 네이티브 라이브러리를 로드하는 방법은 예제외 같이 정적 블록(static block)을 사용하는 것이다


만약 아직 라이브러리를 로드하지 않은 상황에서 네이티브 메서드를 통해 라이브러리에 포함된 C 함수를 호출하면 오류를 발생한다 


때문에 메서드를 호출하는 시점보다 먼저 C 라이브러리를 로딩하기 위해 정적 블록을 사용하는 것이 일반적이다



3. 실제 JNI 를 통해 C로 구현된 함수를 호출할 수 있는 자바 클래스가 완성됐다

이제 main() 함수에서 자바 객체를 만들고 객체의 네이티브 메서드를 호출해서 실제 JNI 네이티브 함수를 호출하면 된다





2단계. 작성한 자바 코드 컴파일


1단계에서 작성한 소스 코드를 javac로 컴파일한다


java HelloJNI.java


컴파일 하면 HelloJNI.class 파일이 생성된다


실행 명령은 다음과 같다


java HelloJNI 



실행하면 hellojni.dll 이 없어서 에러가 난다 다음 단계에서 hellojni.dll 을 만든다




3단계. C/C++ 헤더 파일 생성


이제 자바 코딩은 끝났다


다음으로 HelloJNI 클래스에 선언되어 있는 네이티브 메서드인 printHello() 와 printString() 이 실제 구현된 hellojni.dll 라이브러리 파일을 만들어보자


이전 단계에서 작성한 자바의 네이티브 메서드와 C 함수가 어떻게 연결될까?




JNI 명세에서 정한대로 함수 원형을 작성하면 자바 가상 머신은 해당 함수가 네이티브 메서드와 매핑될 함수라고 식별하게 된다


따라서 네이티브 메서드와 매핑할 C 함수를 작성하려면 JNI 명세에 나온 대로 함수 원형을 만들어야 한다

이러한 작업을 도와주는 것이 바로 javah 라는 툴이다

이 툴은 <JDK_HOME>\bin 에 포함되어 있으며 자바 네이티브 메서드와 연결될 수 있는 C 함수의 원형을 생성해준다


사용법은 다음과 같다


javah <native로 선언된 메서드를 포함한 자바 클래스 이름
































댓글