1. 안드로이드 JNI 로그 남기기
이클립스의 LogCat 에서 jni가 출력되는 것을 보고 싶을 때 유용한다.
jni의 native단에서 printf로 출력되는 것은 adb shell로만 볼 수 있다.
Android.mk에 다음을 추가한다.
LOCAL_LDLIBS := -llog
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := test
LOCAL_SRC_FILES := test.c
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)
C 코드에 다음을 추가한다.
#include <android/log.h>
__android_log_print(ANDROID_LOG_DEBUG, "Tag_Name", "Message...");
레벨은 많다.
ANDROID_LOG_UNKNOWN
ANDROID_LOG_DEFAULT
ANDROID_LOG_VERBOSE
ANDROID_LOG_DEBUG
ANDROID_LOG_INFO
ANDROID_LOG_WARN
ANDROID_LOG_ERROR
ANDROID_LOG_FATAL
ANDROID_LOG_SILENT
#include <jni.h>
#include <android/log.h>
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT jint JNICALL Java_com_google_AddJniActivity_addJNI
(JNIEnv *env, jobject thiz, jint num1, jint num2)
{
__android_log_print(ANDROID_LOG_ERROR, "GOOGLE", "******Message...");
return num1+num2;
}
#ifdef __cplusplus
}
#endif
logcat에 에러가 남는다.
2. 두 개의 모듈을 컴파일 해보기
java == jni-c 이런 상황에서 jni-c 파일이 사용하는 라이브러리가 따로 있는 경우를 의미한다.
즉 jni에서 명시적으로 가지고 쓰는 경우를 의미한다.
first.h
#ifndef FIRST_H
#define FIRST_H
extern int first(int x, int y);
#endif /* FIRST_H */
first.c
#include <android/log.h>
int first(int x, int y)
{
__android_log_print(ANDROID_LOG_DEBUG, "google", "** first.c, first function ");
return x + y;
}
jni 코드 : test.c
#include <jni.h>
#include <android/log.h>
#include "first.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_google_TwoLibs
* Method: add
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_google_TwoLibs_add
(JNIEnv *env, jobject thiz, jint x, jint y) {
__android_log_print(ANDROID_LOG_DEBUG, "google", "*******Message...");
return first(x, y);
}
#ifdef __cplusplus
}
#endif
이런 경우의 android make 파일은 다음과 같이 지정한다.
Android.mk
LOCAL_PATH := $(call my-dir)
## 1st 다음은 libwolib-first 모듈를 만들자
include $(CLEAR_VARS)
LOCAL_MODULE := libtwolib-first
LOCAL_SRC_FILES := first.c
LOCAL_LDLIBS := -llog
include $(BUILD_STATIC_LIBRARY)
## 2nd 다음은 libwolib-second 모듈을 만들자
include $(CLEAR_VARS)
LOCAL_MODULE := libtwolib-second
LOCAL_SRC_FILES := second.c
LOCAL_LDLIBS := -llog
LOCAL_STATIC_LIBRARIES := libtwolib-first
include $(BUILD_SHARED_LIBRARY)
obj/local/armeabi 디렉토리 밑에 보면, first.a 파일과 secod.so 파일이 있는지 확인가능하다.
static lib는 linux archive를 의미한다.
$ ls -al
libtwolib-first.a
libtwolib-second.so
objs
libs/eabi 디렉토리는 static library를 포함하는 so 파일들이 만들어져 있다.
libs/eabi/libtwolib-second.so 파일을 이클립스 프로젝트에서 복사해서 사용한다.
3. module을 export 하기
여러 모듈(c, header) 파일이 있을 때, 여러개의 so파일과 함께 jni가 make 파일을 이용하여 프로그래밍을 할 수 있다.
foo.h
#ifndef FOO_H
#define FOO_H
extern int foo(int x);
#endif /* FOO_H */
foo.c
#include "foo.h"
#include <android/log.h>
/* FOO should be defined to '2' when building foo.c */
#ifndef FOO
#error FOO is not defined here !
#endif
# android.mk 파일에서 설정값에 parameter값을 넣어서 동작되는 지를 확인하는 코드
#if FOO != 2
#error FOO is incorrectly defined here !
#endif
#define LOG_TAG "libfoo"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
int foo(int x)
{
LOGI("foo(%d) called !", x);
return x+1;
}
bar.h
#ifndef BAR_H
#define BAR_H
/* FOO should be defined to '1' here with the magic of LOCAL_EXPORT_CFLAGS */
#ifndef FOO
#error FOO should be defined here !
#endif
#if FOO != 1
#error FOO is not correctly defined here !
#endif
extern int bar(int x);
#endif /* BAR_H */
bar.c
#include "bar.h"
#include <android/log.h>
#define LOG_TAG "libbar"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
int bar(int x)
{
LOGI("bar(%d) called!!", x);
return foo(x)-1;
}
zoo.c
#include "bar.h"
#include <android/log.h>
int something(void)
{
__android_log_print(ANDROID_LOG_INFO, "libzoo", "something() called!!");
return bar(42);
}
test.c
#include <jni.h>
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT jint JNICALL Java_com_google_ModuleExports_foo
(JNIEnv *env, jobject thiz, jint val)
{
return foo(val);
}
JNIEXPORT jint JNICALL Java_com_google_ModuleExports_bar
(JNIEnv *env, jobject thiz, jint val)
{
return bar(val);
}
JNIEXPORT jint JNICALL Java_com_google_ModuleExports_zoo
(JNIEnv *env, jobject thiz, jint val)
{
return something();
}
#ifdef __cplusplus
}
#endif
java파일
public native int foo(int val);
public native int bar(int val);
public native int zoo(int val);
static {
System.loadLibrary("bar");
System.loadLibrary("zoo");
}
}
Android.mk
LOCAL_PATH := $(call my-dir)
# FOO 값을 2로 만들어서 foo.c을 컴파일하고, FOO값을 1로 셋팅한후 archive 파일을 만든다.
include $(CLEAR_VARS)
LOCAL_MODULE := foo
LOCAL_SRC_FILES := foo/foo.c
LOCAL_CFLAGS := -DFOO=2
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/foo
LOCAL_EXPORT_CFLAGS := -DFOO=1
LOCAL_EXPORT_LDLIBS := -llog
include $(BUILD_STATIC_LIBRARY)
# bar.c 를 컴파일하고 static 파일이었던 foo.a 를 모아 bar.so 파일로 만든다.
include $(CLEAR_VARS)
LOCAL_MODULE := bar
LOCAL_SRC_FILES := bar/bar.c
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/bar
LOCAL_STATIC_LIBRARIES := foo
include $(BUILD_SHARED_LIBRARY)
# zoo 파일을 jni파일인 test.c 파일과 함께 컴파일하고, zoo.so 파일로 만든다.
include $(CLEAR_VARS)
LOCAL_MODULE := zoo
LOCAL_SRC_FILES := test.c zoo/zoo.c
LOCAL_SHARED_LIBRARIES := bar
include $(BUILD_SHARED_LIBRARY)
../../ndk-build 결과는 다음과 같은 so 파일이 생성된다.
'안드로이드-iOS-Webkit' 카테고리의 다른 글
안드로이드 bind , service , intent , aidl, 시스템 서비스 예제 - 프로세스 통신 (remote) (1) | 2011.11.24 |
---|---|
안드로이드, 이클립스에서 샘플 예제 보는 방법 (0) | 2011.11.24 |
android ndk r7 버그 (0) | 2011.11.23 |
안드로이드 JNI 개발 준비 #2 (0) | 2011.11.23 |
안드로이드 JNI 개발 준비 #1 (1) | 2011.11.22 |