[개발환경]
1. Cygwin 설치
가. http://www.cygwin.com 에서 다운받는다.
나. Select package 화면에서 gcc-core, g++, make 패키지를 검색해서 설치한다.
2. NDK 설치
가. http://developer.android.com/sdk/ndk/index.html 에서 다운받아 압축을 푼다.
나. 시스템 변수 path영역에 압축푼 경로를 추가한다.
ex) D:\AndroidNDK\android-ndk-r6b
3. 테스트
가. cygwin을 실행해서 >ndk-build 를 실행하여 관련 메시지가 나타나는지 확인한다.
[개발 테스트]
1. Android 프로젝트를 생성한다.
가. 프로젝트 생성 : NDKExam
// =start=======================================================
package org.example.ndk;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class NDKExam extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.main);
TextView tv = new TextView(this);
int x = 1000;
int y = 42;
System.loadLibrary("ndk-exam");
int z = add(x, y);
tv.setText("The sum of " + x + " and " + y + " is " + z);
setContentView(tv);
}
public native int add(int x, int y);
}
// = end =======================================================
2. 헤더 생성은 링크 클릭 => JNI 네이티브 함수 헤더 생성하기
3. JNI 네이티브 함수 구현하기
가. eclipse 패키지에서 "jni" 폴더 생성한다.
나. second.c 파일을 생성한다.
// =start=======================================================
#include "first.h"
#include <jni.h>
jint Java_org_example_ndk_NDKExam_add(JNIEnv* env,
jobject this, jint x,
jint y)
{
return first(x, y);
}
// = end =======================================================
다. first.c 파일을 생성한다.
// =start=======================================================
// first.c
#include "first.h"
int first(int x, int y)
{
return x + y;
}
// = end =======================================================
라. first.h 파일을 생성한다.
// =start=======================================================
// first.h
#ifndef FIRST_H
#define FIRST_H
extern int first(int x, int y);
#endif /* FIRST_H */
// = end =======================================================
마. jni 폴더에 Android.mk 파일을 생성한다.
// =start=======================================================
# 소스 파일 위치
LOCAL_PATH:= $(call my-dir)
# Make 관련 환경 변수를 초기화
include $(CLEAR_VARS)
# 라이브러리를 빌드하기 위한 정보 생성(라이브러리 이름, 소스 코드등)
LOCAL_MODULE := ndk-exam
LOCAL_SRC_FILES := first.c second.c
# 공유 라이브러리 생성
include $(BUILD_SHARED_LIBRARY)
// = end =======================================================
※ Android.mk 작성 문법 관련해서는 <NDK_HOME>\docs 파일 참조
바. <PROJECT-ROOT>ndk-build 실행
사. eclipse에서 android run하여 에뮬이나 디바이스에서 결과 확인.
2011년 11월 16일 수요일
JNI 네이티브 함수 헤더 생성하기
오랜 인고의 이틀간 삽질 끝에 드디어 파일이 생성 되었다.. ㅠㅠ;;
개발환경
OS : Windows 7 pro
Eclipse : Indigo Service Release 1 Build id: 20110916-0149
Java : jdk7
왜 개발환경을 쓴고하니... 인터넷에 찾아보니깐 갖가지 방법들이 나왔는데
내 환경에서는 되지 않았다. 클래스와 android.jar사이 구분자가 ";"로 하니 되는데
어느 블로그에는 ":"로 했더니 되더란다.. 환경은 리눅스환경인듯.. 아무튼
윈도우 환경에서는 아래 코드를 넣고 실행하니 헤더가 생성되었다~~ 아싸...ㅡㅡ;;
D:\project\NDKExam>javah -classpath bin/classes;D:\MyDevelopment\Android\android-sdk\platforms\android-8\android.jar org.example.ndk.NDKExam
아.. 참고로 책에는 이렇게 나와있었다.. 윈도우환경이었다.
H:\project\NDKExam>javah -classpath bin org.example.ndk.NDKExam
개발환경
OS : Windows 7 pro
Eclipse : Indigo Service Release 1 Build id: 20110916-0149
Java : jdk7
왜 개발환경을 쓴고하니... 인터넷에 찾아보니깐 갖가지 방법들이 나왔는데
내 환경에서는 되지 않았다. 클래스와 android.jar사이 구분자가 ";"로 하니 되는데
어느 블로그에는 ":"로 했더니 되더란다.. 환경은 리눅스환경인듯.. 아무튼
윈도우 환경에서는 아래 코드를 넣고 실행하니 헤더가 생성되었다~~ 아싸...ㅡㅡ;;
D:\project\NDKExam>javah -classpath bin/classes;D:\MyDevelopment\Android\android-sdk\platforms\android-8\android.jar org.example.ndk.NDKExam
아.. 참고로 책에는 이렇게 나와있었다.. 윈도우환경이었다.
H:\project\NDKExam>javah -classpath bin org.example.ndk.NDKExam
2011년 11월 11일 금요일
[JNI] C에서 Java호출하기
// JniTest.java
public class JniTest{
public static void main(String[] args){
System.out.print("Hello World " + args[0]);
}
}
// 빌드는 아래와 같이 하면 JniTest.class 파일이 생성된다.
>javac JniTest.java
// JniCall.c
#include
#define PATH_SEPARATOR ';'
#define USER_CLASSPATH "."
void main(){
JNIEnv *env;
JavaVM *jvm;
jint res;
jclass cls;
jmethodID mid;
jstring jstr;
jclass stringClass;
jobjectArray args;
JavaVMInitArgs vm_args;
JavaVMOption options[1];
options[0].optionString = "-Djava.class.path=" USER_CLASSPATH;
vm_args.version = 0x00010002; // 버전정보를 입력한다.
vm_args.options = options; // 옵션할당
vm_args.nOptions = 1; // 옵션의 아규먼트 갯수를 지정한다. 하나이므로 1
vm_args.ignoreUnrecognized = JNI_TRUE; // 자바가상머신이 옵션값이 잘못되어도 무시하고 진행.. 반대는 JNI_FALSE
/* Create the Java VM */
// 자바 가상머신 생성.. env주소를 넘기는건 여기 담아주셔요~~라고하는 것
// env에는 JNI 인터페이스 포인터 주소가 저장된다.
res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
if (res < 0) {
fprintf(stderr, "Can't create Java VM\n");
exit(1);
}
// JniTest 클래스를 로드한다.
cls= (*env)->FindClass(env, "JniTest"); // 빌드된 JniTest.class가 있어야 겠죠.
if (cls == 0) {
fprintf(stderr, "Can't find JniTest class\n");
exit(1);
}
// 자바 소스에서 main함수 ID를 가져온다.
mid = (*env)->GetStaticMethodID(env, cls, "main", "([Ljava/lang/String;)V");
// String jstr = "from C!"; 이녀석이랑 똑같음.
jstr = (*env)->NewStringUTF(env, "from C!");
// String 클래스를 가져온다.
stringClass = (*env)->FindClass(env, "java/lang/String");
// 자바 메인함수가 main(String[] args) 이렇게 구성되어있으니..
// 똑같이 배열로 오브젝트를 구성한다.
args = (*env)->NewObjectArray(env, 1, stringClass, jstr);
// main함수를 호출합니다!
(*env)->CallStaticVoidMethod(env, cls, mid, args);
// 예외처리
if((*env)->ExceptionOccurred(env)){
(*env)->ExceptionDescribe(env);
}
(*jvm)->DestroyJavaVM(jvm);
}
// 빌드는 반드시 Visual Studio Command Prompt를 실행하여 아래 명령어를 실행한다.
cl -I"D:\MyDevelopment\Android\Java\jdk1.7.0\include" -I"D:\MyDevelopment\Android\Java\jdk1.7.0\include\win32" invocationApi.c -link "D:\MyDevelopment\Android\Java\jdk1.7.0\lib\jvm.lib"
// invocationApi.exe 파일이 생성된다.
// 빌드가 완료되었으니 실행해보자!
>invocationApi.exe
Hello World from C!
// 위와 같이 출력되면 OK!
public class JniTest{
public static void main(String[] args){
System.out.print("Hello World " + args[0]);
}
}
// 빌드는 아래와 같이 하면 JniTest.class 파일이 생성된다.
>javac JniTest.java
// JniCall.c
#include
#define PATH_SEPARATOR ';'
#define USER_CLASSPATH "."
void main(){
JNIEnv *env;
JavaVM *jvm;
jint res;
jclass cls;
jmethodID mid;
jstring jstr;
jclass stringClass;
jobjectArray args;
JavaVMInitArgs vm_args;
JavaVMOption options[1];
options[0].optionString = "-Djava.class.path=" USER_CLASSPATH;
vm_args.version = 0x00010002; // 버전정보를 입력한다.
vm_args.options = options; // 옵션할당
vm_args.nOptions = 1; // 옵션의 아규먼트 갯수를 지정한다. 하나이므로 1
vm_args.ignoreUnrecognized = JNI_TRUE; // 자바가상머신이 옵션값이 잘못되어도 무시하고 진행.. 반대는 JNI_FALSE
/* Create the Java VM */
// 자바 가상머신 생성.. env주소를 넘기는건 여기 담아주셔요~~라고하는 것
// env에는 JNI 인터페이스 포인터 주소가 저장된다.
res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
if (res < 0) {
fprintf(stderr, "Can't create Java VM\n");
exit(1);
}
// JniTest 클래스를 로드한다.
cls= (*env)->FindClass(env, "JniTest"); // 빌드된 JniTest.class가 있어야 겠죠.
if (cls == 0) {
fprintf(stderr, "Can't find JniTest class\n");
exit(1);
}
// 자바 소스에서 main함수 ID를 가져온다.
mid = (*env)->GetStaticMethodID(env, cls, "main", "([Ljava/lang/String;)V");
// String jstr = "from C!"; 이녀석이랑 똑같음.
jstr = (*env)->NewStringUTF(env, "from C!");
// String 클래스를 가져온다.
stringClass = (*env)->FindClass(env, "java/lang/String");
// 자바 메인함수가 main(String[] args) 이렇게 구성되어있으니..
// 똑같이 배열로 오브젝트를 구성한다.
args = (*env)->NewObjectArray(env, 1, stringClass, jstr);
// main함수를 호출합니다!
(*env)->CallStaticVoidMethod(env, cls, mid, args);
// 예외처리
if((*env)->ExceptionOccurred(env)){
(*env)->ExceptionDescribe(env);
}
(*jvm)->DestroyJavaVM(jvm);
}
// 빌드는 반드시 Visual Studio Command Prompt를 실행하여 아래 명령어를 실행한다.
cl -I"D:\MyDevelopment\Android\Java\jdk1.7.0\include" -I"D:\MyDevelopment\Android\Java\jdk1.7.0\include\win32" invocationApi.c -link "D:\MyDevelopment\Android\Java\jdk1.7.0\lib\jvm.lib"
// invocationApi.exe 파일이 생성된다.
// 빌드가 완료되었으니 실행해보자!
>invocationApi.exe
Hello World from C!
// 위와 같이 출력되면 OK!
[JNI] Java에서 C 호출하기
// HelloJNI.java
class HelloJNI
{
//네이티브 메서드 선언
native void printHello();
native void printString(String str);
// library loading
static { System.loadLibrary("hellojni"); }
public static void main(String args[])
{
HelloJNI myJNI = new HelloJNI();
myJNI.printHello();
myJNI.printString("Hello World from printString fun");
}
}
// 빌드는 아래와 같이 진행
>javac HelloJNI.java
// HelloJNI.class 파일이 생성된다.
// HelloJNI.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class HelloJNI */
#ifndef _Included_HelloJNI
#define _Included_HelloJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloJNI
* Method: printHello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloJNI_printHello
(JNIEnv *, jobject);
/*
* Class: HelloJNI
* Method: printString
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_HelloJNI_printString
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
// hellojni.c
#include "HelloJNI.h"
#include
JNIEXPORT void JNICALL Java_HelloJNI_printHello (JNIEnv *env, jobject obj)
{
printf("Hello World!\n");
return;
}
JNIEXPORT void JNICALL Java_HelloJNI_printString (JNIEnv *env, jobject obj, jstring string)
{
const char *str = (*env)->GetStringUTFChars(env, string, 0);
printf("%s!\n", str);
return;
}
// 빌드는 아래와 같이 진행
>cl -I"D:\MyDevelopment\Android\Java\jdk1.7.0\include" -I"D:\MyDevelopment\Android\Java\jdk1.7.0\include\win32" -LD hellojni.c -Fehellojni.dll
// Fehellojni.dll 파일이 생성된다.
// 빌드가 완료되었으니 이제 실행해보자!
>java HelloJNI
Hello World!
Hello World from printString fun!
// 위 처럼 출력결과가 나타난다.(실행된 코드 그대로 올렸으니 소스상 문제는 없을것이다.)
class HelloJNI
{
//네이티브 메서드 선언
native void printHello();
native void printString(String str);
// library loading
static { System.loadLibrary("hellojni"); }
public static void main(String args[])
{
HelloJNI myJNI = new HelloJNI();
myJNI.printHello();
myJNI.printString("Hello World from printString fun");
}
}
// 빌드는 아래와 같이 진행
>javac HelloJNI.java
// HelloJNI.class 파일이 생성된다.
// HelloJNI.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class HelloJNI */
#ifndef _Included_HelloJNI
#define _Included_HelloJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloJNI
* Method: printHello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloJNI_printHello
(JNIEnv *, jobject);
/*
* Class: HelloJNI
* Method: printString
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_HelloJNI_printString
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
// hellojni.c
#include "HelloJNI.h"
#include
JNIEXPORT void JNICALL Java_HelloJNI_printHello (JNIEnv *env, jobject obj)
{
printf("Hello World!\n");
return;
}
JNIEXPORT void JNICALL Java_HelloJNI_printString (JNIEnv *env, jobject obj, jstring string)
{
const char *str = (*env)->GetStringUTFChars(env, string, 0);
printf("%s!\n", str);
return;
}
// 빌드는 아래와 같이 진행
>cl -I"D:\MyDevelopment\Android\Java\jdk1.7.0\include" -I"D:\MyDevelopment\Android\Java\jdk1.7.0\include\win32" -LD hellojni.c -Fehellojni.dll
// Fehellojni.dll 파일이 생성된다.
// 빌드가 완료되었으니 이제 실행해보자!
>java HelloJNI
Hello World!
Hello World from printString fun!
// 위 처럼 출력결과가 나타난다.(실행된 코드 그대로 올렸으니 소스상 문제는 없을것이다.)
[JNI] 개발 환경 설정
[개발환경]
1. http://www.microsoft.com/express/download/ 경로에서
Visual Studio 2010 Express Professional 버전을 설치한다.
반드시 2010일 필요는 없음
2. 설치가 완료되면 Visual Studio Command prompt 실행
JNI 소스 빌드시 2번에서 실행한 커맨드 창에서 명령어 입력해서 빌드해야한다.
1. http://www.microsoft.com/express/download/ 경로에서
Visual Studio 2010 Express Professional 버전을 설치한다.
반드시 2010일 필요는 없음
2. 설치가 완료되면 Visual Studio Command prompt 실행
JNI 소스 빌드시 2번에서 실행한 커맨드 창에서 명령어 입력해서 빌드해야한다.
피드 구독하기:
글 (Atom)