JNI + Android

JNI 사용 구조는 다음 그림으로 요약할 수 있습니다.

Android에서 사용하는데 필요한 것은 5 단계에서 Cross Compiler로 컴파일 되어야 한다는 것입니다.

그리고 컴파일 된 결과가 “.DLL”이 아니라 “.so” 파일로 나온다는 거겠죠.

Cross Compiler는 http://www.codesourcery.com/gnu_toolchains/arm/download.html 에서 구할 수 있습니다.

그런데 gcc의 -shared 옵션으로 .so 파일을 만들고 실행해보면, 사용될 때 App가 죽어버립니다.

이는 precompiled-library에 관련된 문제로 보이는데, 이를 위해서 컴파일 단계의 ldscript를 수정해서 사용합니다.

http://honeypod.blogspot.com/2007/12/shared-library-hello-world-for-android.html 를 참고하면 다음과 같은 부분을 볼 수 있습니다.

Now, the default linker script need to be modified. The default
linker script is available at
$toolchains_home/arm-none-linux-gnueabi/lib/ldscripts/armelf_linux_eabi.xsc.
Copy it to the current directory. Comment out three lines and add one
line replacing the first commented out line.

/* . = ALIGN (CONSTANT (MAXPAGESIZE)) – ((CONSTANT (MAXPAGESIZE) – .) & (CONSTANT (MAXPAGESIZE) – 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); */
. = .; /* this line replaces the line above */

/* . = DATA_SEGMENT_RELRO_END (0, .); */

/* . = DATA_SEGMENT_END (.); */

$toolchains_home/arm-none-linux-gnueabi/lib/ldscripts/ 경로에 있는 armelf_linux_eabi.xsc 파일을 수정해야 한다는 이야기입니다.

수정한 파일을 사용해서 다음 명령으로 컴파일하면 실제 안드로이드에서 동작하는 라이브러리를 만들 수 있습니다.

arm-none-linux-gnueabi-gcc -I/usr/lib/jvm/java-6-sun/include -I/usr/lib/jvm/java-6-sun/include/linux -fpic -c <JNI 함수 구현소스>.c

arm-none-linux-gnueabi-ld -T armelf_linux_eabi.xsc -shared -o <library명>.so <Object파일>.o

그리고 emulator 실행 후 다음 명령으로 에뮬레이터에서 실행가능합니다.

adb push <라이브러리>.so /system/lib
adb install <JNI를 사용하는 Android APP>.apk

내가 생각하는 KLDP의 장점 중 한가지..

간단한 질문에도 생각해 볼 수 있는 좋은 답변들과 논쟁들이 많이 달린다는 것이다.

JNI의 C/C++에서의 포인터 관련 처리를 어떻게 하는지 찾아보려고 무작정 검색하던 중

KLDP의 글 하나가 걸려들었다.

바로 이 글!

자바에서의 포인터는 있는가? 라는 논쟁이 나오고, 포인터는 그냥 개념에 불과하다는 이야기,

반대로 자바에는 포인터가 없다는 이야기, 포인터를 레퍼런스의 일종으로 보아야 된다는 이야기까지…

이런 답글을 살펴보다 보면, 내 자신이 알고 있는 지식이 얼마나 보잘 것 없는지..

그리고, 정확한 용어의 사용과 이해가 얼마나 중요한 것인지 생각해보게 된다.

교수님들이 말씀하시던,

용어의 의미를 정확히 알고 있어야 하고, 그 의미를 정확히 이해해야 한다는 말씀에 고개가 끄덕여진다.

아무튼 실제 글보다 댓글에서 줄줄이 캐어내듯 뭔가가 나오는 것이 KLDP의 한 장점이 아닐까 한다. ㅋㅋ

쓰라고 주는 툴을 못 쓸때..

정말 자괴감에 빠집니다… 으으으으………….

JNI라는 걸 좀 해보려고 javah 라는 header 파일 생성기를 좀 써보려고 노력중이었습니다.

근데 아무리 쓰여진데로

javah -classpath ../../android.jar;../bin/classes; org.apache.NativeAdd

를 쳐도 안되는 겁니다.

1. 경로명이 잘못됐나?
2. 경로명을 따옴표로 묶어주어야 하나?
2. 클래스 파일을 잘못 만들었나?
3. android.jar하고 뭔가 관련이 있나?
4. access 할 수 없다니.. 권한 문제인가..
5. 파일을 왜 못찾는다지?
……

결국 원인은 무엇인고 하니..

javah의 -verbose 옵션을 켰더니 다음과 같이 나오는군요.

dasomoli@dasomoli-ubuntu804:~/CallNative/src$ javah -classpath “../../android.jar;../bin/classes;” -verbose org.apache.NativeAdd
error: cannot access org.apache.NativeAdd
class file for org.apache.NativeAdd not found
javadoc: error – Class org.apache.NativeAdd not found.
[
Search Path:
/usr/lib/jvm/java-6-sun-1.6.0.06/jre/lib/resources.jar:/usr/lib/jvm/java-6-sun-1.6.0.06/jre/lib/rt.jar:/usr/lib/jvm/java-6-sun-1.6.0.06/jre/lib/sunrsasign.jar:/usr/lib/jvm/java-6-sun-1.6.0.06/jre/lib/jsse.jar:/usr/lib/jvm/java-6-sun-1.6.0.06/jre/lib/jce.jar:/usr/lib/jvm/java-6-sun-1.6.0.06/jre/lib/charsets.jar:/usr/lib/jvm/java-6-sun-1.6.0.06/jre/classes/../../android.jar;../bin/classes;
]

Error: No classes were specified on the command line.  Try -help.

아시겠습니까?

네.. 그렇습니다. ‘;’ 대신 ‘:’를 써주어야 하는 겁니다.

이렇게 해주어야 되는 것이었습니다.

javah -classpath ../../android.jar:../bin/classes: org.apache.NativeAdd

그래서 결과는 다음과 같이 나옵니다.

dasomoli@dasomoli-ubuntu804:~/CallNative/src$ javah -classpath “../../android.jar:../bin/classes:” -verbose org.apache.NativeAdd
[ Search Path: /usr/lib/jvm/java-6-sun-1.6.0.06/jre/lib/resources.jar:/usr/lib/jvm/java-6-sun-1.6.0.06/jre/lib/rt.jar:/usr/lib/jvm/java-6-sun-1.6.0.06/jre/lib/sunrsasign.jar:/usr/lib/jvm/java-6-sun-1.6.0.06/jre/lib/jsse.jar:/usr/lib/jvm/java-6-sun-1.6.0.06/jre/lib/jce.jar:/usr/lib/jvm/java-6-sun-1.6.0.06/jre/lib/charsets.jar:/usr/lib/jvm/java-6-sun-1.6.0.06/jre/classes/../../android.jar:../bin/classes: ]
[Creating file org_apache_NativeAdd.h]
[search path for source files: ../../android.jar,../bin/classes,.]
[search path for class files: /usr/lib/jvm/java-6-sun-1.6.0.06/jre/lib/resources.jar,/usr/lib/jvm/java-6-sun-1.6.0.06/jre/lib/rt.jar,/usr/lib/jvm/java-6-sun-1.6.0.06/jre/lib/sunrsasign.jar,/usr/lib/jvm/java-6-sun-1.6.0.06/jre/lib/jsse.jar,/usr/lib/jvm/java-6-sun-1.6.0.06/jre/lib/jce.jar,/usr/lib/jvm/java-6-sun-1.6.0.06/jre/lib/charsets.jar,/usr/lib/jvm/java-6-sun-1.6.0.06/jre/classes,/usr/lib/jvm/java-6-sun-1.6.0.06/jre/lib/ext/dnsns.jar,/usr/lib/jvm/java-6-sun-1.6.0.06/jre/lib/ext/sunpkcs11.jar,/usr/lib/jvm/java-6-sun-1.6.0.06/jre/lib/ext/localedata.jar,/usr/lib/jvm/java-6-sun-1.6.0.06/jre/lib/ext/sunjce_provider.jar,../../android.jar,../bin/classes,.]
[loading ../bin/classes/org/apache/NativeAdd.class]
[loading java/lang/Object.class(java/lang:Object.class)]
[loading java/lang/Throwable.class(java/lang:Throwable.class)]
[loading java/lang/Class.class(java/lang:Class.class)]
[done in 717 ms]

이럴 때… 정말 자괴감에 빠집니다..ㅠㅠ

구글 Android SDK 셋팅(우분투 8.04 기준)

1. http://code.google.com/android 에서 Download the SDK 를 클릭

2. 라이센스 확인

3. Linux (i386) 용 zip 다운로드

4. 압축 해제.

4.1. 계정의 .profile 맨 마지막에 다음 내용을 추가하고 다시 로그인 << 여기 추가되었습니다.

PATH=”$HOME/android/tools:$PATH”
PATH=”$HOME/eclipse/tools:$PATH”

4.2. 압축해제한 디렉토리를 ~/android 로 symbolic link. << 여기 추가되었습니다.

5. JDK 설치(sudo apt-get install sun-java6-jdk)

6. http://code.google.com/android 의 Docs 를 눌러 Getting started / Installing the SDK

7. System and Software Requirements 의 Eclipse 를 눌러 Eclipse IDE for Java Developers를 다운로드

8. 홈폴더에서 압축해제.

[#M_* 바탕화면에서 실행하기 위해 $HOME/바탕화면/eclipse.desktop 생성|<<접기>>| [Desktop Entry]
Version=1.0
Exec=/home/dasomoli/eclipse/eclipse
Icon=/home/dasomoli/eclipse/icon.xpm
Name=Eclipse
GenericName=Development Tools
Comment=Eclipse
Encoding=UTF-8
Terminal=false
Type=Application
Categories=Application;Development;_M#]
9. Eclipse에서 WST 설치

10. Eclipse에서 https://dl-ssl.google.com/android/eclipse/ 를 추가하고 설치

11. Eclipse에서 Window/Preference 의 Android 의 SDK Location 을 아까 SDK의 압축 해제 디렉토리로 지정

12. 프로젝트 시작!

소 그리기 과제 중!

컴퓨터 그래픽스 두번째 과제!

소를 그리는 게 과제입니다. ㅋㅋ MFC를 연결하거나 뭐 그러시더니 그냥 WIN32 Console App로 짜오시라는군요-_-

그리다 보니 소가 삐죽삐죽하길래 뭐지! 했더니 예전에 제출한 선그리기 함수가 좀 잘못되어 있었습니다-_-
사용자 삽입 이미지
암튼 그리고나서! 마우스 이벤트로 카메라 위치도 바꿀 수 있도록 하고 나니 이리저리 빙글빙글 돌리면서 보는 것이 재밌네요. 흐흐..
사용자 삽입 이미지

OpenGL MFC Glut Tutorial Lesson1 + 상자 색 바꿔보기!

학교에서 컴퓨터 그래픽스 수업을 듣고 있습니다.

첫번째 과제는 GLUT를 이용한 선 그리기 + 삼각형 색 채우기 였는데요. 두번째 과제가 나올 듯 합니다.
Projection 관련 과제로 설명을 들었는데 교수님께서 연휴 때문인지 올리시질 않으시네요. 기한은 다가오는데….;;;

두 가지(Perspective/Orthogonal) Projection에 대해 구현해 가야 하므로 두 개를 내던가, 혹은 창 제어를 가능하게 해서 하나로 통합해서 내던가 둘 중 아무거나 선택해서 내면 될 거 같아서 교수님께서 언급하신 MFC로 제어하는 방법에 대해서 찾아보았는데요.
이 곳(http://www.kencocomputers.com/tutorials/)에 잘 설명되어 있네요^^

Lesson1을 따라해보다가 다이얼로그를 숨기지 않고 컨트롤들을 배치해서 값을 변경가능한가 테스트해보고 싶은 마음이 들어 박스의 색을 바꾸는 코드를 추가해서 한번 해 보았습니다.

일단 Lesson1을 따라해봅니다.
그리고 먼저 Play 버튼의 이벤트 핸들러 함수 내용 중 “this->ShowWindow(SW_HIDE)” 를 주석처리합니다.

void CGLUTLesson1Dlg::OnOK()
{
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);//set out options to RGB, double buffered and depth
    glutCreateWindow(“MFC Glut Lesson1”);//give the glut window a title
    // set glut callback functions
    glutDisplayFunc(display);//set our display callback
    glutReshapeFunc(resize);//set out resize callback
    //this->ShowWindow(SW_HIDE);// hide the mfc starter when the glut window opens
    glutMainLoop(); //start the glut main loop   

    CDialog::OnOK();
}

그리고 MFCOpenGL(원문에서는 MFCopenGL입니다.) 클래스에 float 형 변수 m_R, m_G, m_B를 추가해 줍니다.
이 값들을 다이얼로그에서 건드릴 것이므로 m_R, m_G, m_B 변수에 대한 Get/Set 함수를 추가하고, 세 개를 한꺼번에 바꾸는 SetColor 함수를 추가합니다. 그리고 m_R, m_G, m_B를 protected 속성으로 바꿉니다.

class MFCOpenGL 
{
public:
    …
    void SetColor(float r, float g, float b);

    void SetR(float r);
    void SetG(float g);
    void SetB(float b);

    float GetR();
    float GetG();
    float GetB();

protected:   
    float m_R;
    float m_G;
    float m_B;

};

뭐, 굳이 SetColor과 SetR/G/B, GetR/G/B 함수는 안써도 다 아시겠죠? ㅋㅋ

그리고 MFCOpenGL::display() 함수의 “glColor3f(1.0f, 0.0f, 0.0f);” 를 “glColor3f(m_R, m_G, m_B);”로 바꾸어 추가한 변수들로 그리도록 해줍니다.

void MFCOpenGL::display(void)
{
    glClearColor(0,0,0,0);//set the background color to black
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);
    glColor3f(m_R, m_G, m_B); //set cube color
    glutWireCube(30); //use the premade glut function to draw a wire cube of size 30
    glutSwapBuffers();
}

원래 값이 각각 1.0f, 0.0f, 0.0f 였으므로 생성자에서 이 값들을 m_R, m_G, m_B 에 넣어주면 좋겠네요.

MFCOpenGL::MFCOpenGL()
{
    m_R    = 1.0f;
    m_G    = 0.0f;
    m_B    = 0.0f;
}

그리고나서 원래 다이얼로그에 에디트 창 3개를 추가하고 각각에 연결된 float형 변수(m_R/m_G/m_B)를 추가합니다. 또 각 변수들로 SetColor을 호출하고 다시 그려줄 버튼도 하나 추가해 줍니다.

사용자 삽입 이미지

창이 뜰 때 만들어질 창의 색 값이 써지면 좋겠군요. OnInitDialog 함수에서 GetR/G/B함수를 이용해서 얻어오죠~

BOOL CGLUTLesson1Dlg::OnInitDialog()
{
    …

    // TODO: Add extra initialization here
    m_R = gl.GetR();
    m_G = gl.GetG();
    m_B = gl.GetB();

    UpdateData(FALSE);
   
    return TRUE;  // return TRUE  unless you set the focus to a control
}

그리고, SetColor버튼을 눌렀을 때 SetColor 함수를 호출하면 될 것 같군요. 값을 얻어와서 호출한 후에 display함수를 호출해서 그려줍시다.

void CGLUTLesson1Dlg::OnButtonSetColor()
{
    UpdateData(TRUE);
   
    gl.SetColor(m_R, m_G, m_B);
   
    display();
   
}

어디 그럼 이제 띄워볼까요?

사용자 삽입 이미지
잘~ 되네요. 흐흐~

컴퓨터 그래픽스 두번째 과제가 나오면 이 걸 좀 이용해서 이런식으로 해서 내야겠습니다. 흐흐..

Xsupplicant 1.9.5(CVS) 소스 설치 on 우분투 8.04 beta

졸업작품 프로젝트로 xsupplicant 관련 작업을 하고 있습니다.
그를 위해서 리눅스 환경에서 xsupplicant 컴파일 작업이 필요해서 최신 버전을 CVS를 통해 받아와서 컴파일해보았습니다.
1.2.8 버전을 설치하려니 이것저것 건드려줘야 할 것들이 많아서 최신 버전을 빌드하는 것보다 더 힘들군요-_-
iwlib.h 를 찾을 수 없다는 에러부터.. linux/compiler.h 가 없다는 에러.. #define HEADER_KERNEL 을 지워줘야 한다는 이야기도 있고.. 아무튼 이래저래 삽질 중 최신버전 설치가 더 쉽게 되어 정리합니다.

설치는 우분투 8.04 beta를 VMWare 6.0.3 에서 설치한 후에 진행하였습니다.
회색배경은 직접 입력하는 부분이고, 노란배경은 화면 메시지 입니다.

1. 우분투 8.04 beta 설치

2. build-essential 설치
 – libc6-dev, libc-dev, gcc, g++, make, dpkg-dev

sudo apt-get install build-essential

3. CVS 설치

sudo apt-get install cvs

4. XSupplicant CVS 저장소 익명 로그인

cvs -d:pserver:anonymous@open1x.cvs.sourceforge.net:/cvsroot/open1x login
Logging in to :pserver:anonymous@open1x.cvs.sourceforge.net:2401/cvsroot/open1x
CVS password:
<ENTER>
cvs login: CVS password file /home/dasomoli/.cvspass does not exist – creating a new file

5. XSupplicant 소스를 CVS 에서 받아오기


cvs -z3 -d:pserver:anonymous@open1x.cvs.sourceforge.net:/cvsroot/open1x co -P xsupplicant

6. 받은 소스가 들어있는 디렉토리로 들어가기

cd xsupplicant

7. Autoconf 설치

sudo apt-get install autoconf

8. automake1.9 설치
 automake를 설치하면 1.10 버전이 설치되는데, 이 것으로 automake를 하면 되지 않더군요.

sudo apt-get install automake1.9

9. libssl-dev 설치

sudo apt-get install libssl-dev

10. libiw-dev 설치

sudo apt-get install libiw-dev

11. libxml2-dev 설치

sudo apt-get install libxml2-dev

11. configure와 make를 위해서..

automake –add-missing
autoreconf

12. configure

./configure –prefix=/usr

13. 컴파일

make

14. 설치

sudo make install

15. 설치 확인

xsupplicant
Starting XSupplicant v. 1.9.5.071009.080121
Found 0 other supplicants and wireless managers.
File /etc/xsupplicant.conf can’t be accessed
Tue Apr 15 00:25:17 2008 – File /etc/xsupplicant.conf can’t be opened.  Do you have rights to it?
Couldn’t read the configuration file.  Building defaults.

흐흐.. 이제 좀 건드려 볼 수 있겠군요.. 🙂

우분투 카운터!

우분투 8.04의 출시일이 얼마 남지 않았네요!

초보 리눅서님의 블로그에서 우분투 베타판 출시 소식과 함께 배너에 대한 이야기를 듣고 추가해 보았습니다. 🙂

왼쪽을 보니 오늘로써 29일 남았다고 나오네요. 흐흐.

흐흐.. 기대됩니다.

OOXML: 뭐가 그리 대단한가? (한글)

OOXML: 뭐가 그리 대단한가?

 위 글은 10여년 동안 ISO C 표준 위원회에 자원하여 활동한 경험이 있는 표준화에 관심이 많은 필자가 정치적인 입장이 아니라 기술적인 측면에서 OOXML을 표준으로 취급해서 안 되는 이유를 밝히는 글입니다.

 먼저 표준을 정립하는 목적을 상기시키고 나서.. OOXML 이 표준으로 채택될 수 없는 이유를 세 가지로 정리하여 밝힙니다. 그 이유는 다음과 같습니다.

  1. 불합리한 요구사항
  2. 불충분한 명세
  3. 고유한 기능

 1. 불합리한 요구사항의 요점은 스펙이 해석에 따라 다의적인 요구사항을 포함함으로써 구현을 불가능하도록 한다는 것입니다.
 2. 불충분한 명세의 요점은 구체적인 명세를 의도적으로 제공하지 않으므로써 구현을 불가능하게 한다는 것입니다.
 3. 고유한 기능-많은 표준 전문가들이 가장 분노한다는-의 요점은 마이크로소프트 오피스에만 종속적인 기능을 가지고 있다는 것입니다.

 마지막으로 XML이 문서 표준으로 적합하지 않은 것은 아니며, 가장 큰 경쟁자인 ODF에 대해서 소개하면서 문서 내용 자체를 기술하려고 한다는 점을 밝히고 있습니다.

 관심있으신 분은 전문을 한번쯤 읽어보시길 권합니다. 그리고! 반대 서명운동에 동참하세요! 🙂

OOXML 표준 채택 반대 두번째 서명 시작!

두번째 OOXML 서명 시작!

MS의 OOXML의 표준 채택 관련 반대에 대한 두번째 서명운동이 시작되었습니다.

링크한 글은 KLDP의 channy님의 글이고 실제 서명 페이지는 이 곳 입니다.

왼쪽의 배너를 누르시면 KLDP의 페이지로 연결됩니다.

설명이나 다른 분들의 반응들을 볼 수 있으니 참고하시라고 그 쪽으로 연결해 놨습니다.

한 번 보시고, 자신의 뜻에 맞으신다면 서명해 주세요.