制作 cygwin 环境下的 Cross tool chain

 

Google Android

os-bot-launch2.png Android is the first free, open source, and fully customizable mobile platform. Android offers a full stack: an operating system, middleware, and key mobile applications. It also contains a rich set of APIs that allows third-party developers to develop great applications.

制作 cygwin 环境下的 Cross tool chain

在完全开源前,很多开发者在用 CodeSourceryGNU Toolchains for ARM 。现在简单了, 下载到源码后,在 prebuild 目录下就有完整的 toolchain 用了。如果需要在其他系统环境下使用,可以去下载 android-toolchain-20081019.tar.bz2 源码重新编译。在 cygwin 下编译时,先检查一下 gcc make Flex bison gettext-devel 等是否装全(编译过程中会用到 msgfmt 命令,cygwin 把它放到 gettext-devel 包里了),然后按照其 readme.txt 里的 linux 方式编译就可以了。cgywin 下有时会出现文件写失败的错误,用 chmod +w 修改即可解决。
在 <android source>/build/core/combo 目录下的 linux-arm.mk 文件对我们来说非常有帮助,其中 C_INCLUDES 描述 C 语言的所有头文件位置,在 android source 里找到这些目录,并复制到新编译好的 <toolchain>/arm-eabi/include 目录下,动态库在编译过的 <android source>/out/target/product/generic/system/lib  目录下,也可以从 Android SDK 的模拟器中 /system/lib 下找到这些文件,并复制到 <toolchain>/arm-eabi/lib 目录下。在 <android source>/build/core 下有 armelf.x armelf.xsc ,是以后编译必须的连接脚本。在 <android source>/out/target/product/generic/obj/lib 下的 crtbegin_static.o crtbegin_dynamic.o crtend_android.o  编译时还要根据自己情况选择并连接到可执行文件中去,当然也可以在程序 main 函数后加如下函数代替。
 
      void _start(int argc, char **argv) { exit( main(argc, argv) ); }

 
First native C application on android

制作好了 toolchain ,就可以写个 hello.c 测试一下了。代码如下:

#include <stdio.h>
int main(int argc, char **argv)
{
printf("Hello World!\n");
return 0;
}

编译命令:

$ arm-eabi-gcc -nostdlib -Bdynamic -Wl,-T,armelf.x -Wl,-dynamic-linker,/system/bin/linker \
-include AndroidConfig.h -lc -o hello hello.c crtbegin_dynamic.o crtend_android.o
$ adb push hello /data
$ adb shell chmod 777 /data/hello
$ adb shell /data/hello
Hello World!
$

哈哈,Android 之旅开始了…


Shared library for android


接下来测试 shared library ,编写代码 libhello.c :

#include <stdio.h>
int sayhello(char *name)
{
printf("Hello %s\n", name);
return 0x12345;
}

编写代码 hello2.c :

extern int sayhello(char *name);
int main(int argc, char **argv)
{
sayhello("World!");
return 0;
}

编译代码及测试运行:

$ arm-eabi-gcc -nostdlib -Wl,-T,armelf.xsc -Wl,-shared,-Bsymbolic -lc -o libhello.so libhello.c
$ arm-eabi-gcc -nostdlib -Bdynamic -Wl,-T,armelf.x -Wl,-dynamic-linker,/system/bin/linker \
  -L./ -lc -lhello -o hello2 hello2.c crtbegin_dynamic.o crtend_android.o
$ adb push libhello.so /data
$ adb push hello2 /data
$ adb shell chmod 777 /data/hello2
$ adb shell /data/hello2
Hello World!
$

呵呵,又迈进一步 ...


The Java Native Interface (JNI) for Android
 
在 eclipse 里新建一个 android 项目,新增加一个类 hello.java :

package cn.oopsware.hello;

public class hello {
static {
try {
System.load("/data/lib/libhello_jni.so");
} catch (Exception e) {}
}
public native int test1();
public native int test2(int[] name);
}

修改主程序 onCreate 的代码,用来调用显示结果:

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
hello h = new hello();
TextView tv = new TextView(this);
tv.setText( Integer.toHexString( h.test1() ) );
setContentView(tv);
}

android 使用的 JNI 头文件在目录 <android source>/dalvik/libnativehelper/include/nativehelper 下。也许是为了提高 android 映射库函数的速度,android 另加了两个函数,在加载和释放库时被VM调用,即:jint JNI_OnLoad(JavaVM* vm, void*)  和 void JNI_OnUnload(JavaVM* vm, void*)  。通过 JNIEnv 的 RegisterNatives 用法把一个 JNINativeMethod 数组注册到 VM 。 <android source>/dalvik/libcore/dalvik/src/main 加有个简单的例子,可以帮助理解 JNINativeMethod 中 signature 的写法。 共享库代码 libhello_jni.c :

#include "jni.h"

static int test1(JNIEnv* env, jclass clazz)
{
return 0x654321;
}

static int test2(JNIEnv* env, jclass clazz, jarray a)
{
return 0x765432;
}

#define gClassName "cn/oopsware/hello/hello"

static JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{ "test1",  "()I",  test1 },
{ "test2",  "([I)I", test2 },
};

jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
JNIEnv *env;
jclass cls;
if ( (*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_4) ) return JNI_ERR;
cls = (*env)->FindClass(env, gClassName);
(*env)->RegisterNatives(env, cls, &gMethods[0], 2);
return JNI_VERSION_1_4;
}

void JNI_OnUnload(JavaVM* vm, void* reserved)
{
JNIEnv *env;
jclass cls;
if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_4)) return;
cls = (*env)->FindClass(env, gClassName);
(*env)->UnregisterNatives(env, cls);
}

编译并上传到模拟器:

$ arm-eabi-gcc -nostdlib -Wl,-T,armelf.xsc -Wl,-shared,-Bsymbolic \
-lc -o libhello_jni.so hello_jni.c

$ adb push libhello_jni.so data/bin/libhello_jni.so

在 eclipse 里运行 android 项目,即可看到正确结果。测试代码及编译好的测试.so 和 .apk,可下载下面的附件 jni_test.zip 。

附件 (1)

  • jni_test.zip 11k - 创建时间 2008-12-20 上午5:55,创建人 Du Qiang (版本 1)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
================================================================================简体中文 Telnet 是免费的。OopsWare 拥有简体中文 Telnet 的著作权。请在使用本软件前阅读如下协议:1. 您可以任意使用和复制本简体中文 Telnet;2. 您可以将本简体中文Telnet复制提供给他人,但在未经许可的情况下,不得将本简体中文 Telnet 用于商业用途;3. 本软件附带源程序仅用于学术交流,但您无权对软件的程序和文档进行修改再发布;4. OopsWare 对本简体中文 Telnet 的使用不提供任何担保,就衍生性损害不负赔偿责任。http://oopsware.delphibbs.com/E-Mail:oops@jn-public.sd.cninfo.net================================================================================用TOopsConsole控件(scoansi、ansi)制作的仿真终端,支持中文、彩色、表格... 这还是一个尚未完成的版本,其在使用 SCO Unix 中的 vi 时输入中文有问题。 问题的解决方法刚刚找到,但是还没来得及修改程序。问题(1):vi 中输入中文不能正常显示,而是输出xxx 形式的八进制字符串。解决方法:并不是本Telnet的毛病,Unix是英文版,当然不识别大于0x7F的字符, 安装汉字环境后问题就解决了!问题(2):容易出现“半个汉字”的现象。解决方法:看看原程序文件OopsConsole.pas 中Paint过程,为了防止屏幕重画占用过多系统资源,仅重画了当前操作的字符(汉字),所以... 问题(3):中文输入法无法光标跟随。有待解决! (如果您对其感兴趣就拉回去看看吧!有好的建议别忘了通知我!)。[Jan 8, 2001]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值