转载请注明出处为KlayGE游戏引擎,本文的永久链接为http://www.klayge.org/?p=1697

Android从NDK r5之后,就支持使用纯C/C++编写App。但按照NDK中的例子,纯C/C++写的代码总是异于其它平台。它的程序入口是void android_main(struct android_app* state),而不是其它平台通用的int main()。

就其本质,是因为android上没有其它平台的CRT来调用入口,而是通过android_native_app_glue这个库把native的代码和java端粘起来。所以,我们可以通过修改android_native_app_glue库,来实现和其它平台一样的int main()入口。

可以观察到,android_native_app_glue需要提供给android_main一个关键的参数:android_app指针。同时,android_main里面需要调用android_dummy()这个空函数来保证android_native_app_glue不会被优化器删掉。这里就拿它下刀了,具体步骤是:

1. 在android_native_app_glue.c里声明一个全局变量struct android_app* g_android_app。该变量在android_app_entry中赋值。

2. 把无用的android_dummy()改称返回该全局变量的

1
2
3
4
struct android_app* get_app()
{
    return g_android_app;
}

3. 在android_native_app_glue.h中,把extern void android_main(struct android_app* state)的声明改成extern int main()。

4. 在android_app_entry中,把对android_main的调用改成对main的调用。

5. 把C/C++端的android_main实现改成main,并把它对android_dummy()的调用改成struct android_app* state = get_app();。

大功告成!因为新的main中必然要通过调用get_app获得state,所以android_native_app_glue肯定不会被优化器干掉。同时可以用通用的main作为入口了,一举两得。需要注意的是,这个main的返回值是int而不是void,所以需要显式写上return 0。(顺便说一下,谭浩强的C语言教材以前都是用void main()这种70年代就已经遗弃的错误写法,不知道现在是不是还在错。)

这就是我修改过的android_native_app_glue。你可以用它来替换掉NDK的,或者直接加在你的项目中。android_native_app_glue.7z