zengl v1.3.1 , 增加了android工程目录,对android平台下的ARM GCC进行了测试,使用android ndk开发了一个手机上运行zengl脚本的app,arm gcc下默认约定char类型为unsigned无符号类型...

    v1.3.1版本的下载地址如下:

    github项目地址为:https://github.com/zenglong/zengl_language/  选择右侧的Download Zip或Clone in Desktop (github上只包含源代码,不包含apk安装包,apk安装包放在百度盘和sourceforge的zip压缩包内)。

    百度盘共享链接地址:http://pan.baidu.com/s/1kTynjD1 这是一个zip压缩包,解压后可以看到linux ,windows,mac和android目录,分别为三个PC操作系统和Android系统下的源码和编译器配置,windows目录中既包含用于vs2008的sln解决方案,还包含用于vc6的dsw工作空间,android目录中包含android工程文件,需要android ndk来编译和调试,该zip压缩包中还包括apk安装包,安装该apk后,可以在手机或平板(平板没测试)上编写运行简单的zengl脚本(只有几个基础的模块函数,其他模块函数需要自行在C源码中添加)。

    sourceforge.net上的项目地址为:https://sourceforge.net/projects/zengl/files/ (里面有所有历史版本的压缩包,包括v1.3.1的zip包,该包里也含有apk安装包)。

    在linux中进行make之前,如果不是root用户,就请用 "su" 之类的命令提权,因为make生成libzengl.so后,会copy这个.so文件到/usr/lib目录中(该目录需要root权限才能进行写入操作),这样可执行文件zengl和encrypt才能链接和使用libzengl.so的动态链接库,详情可以查看makefile,只有libzengl.so是zengl语言的核心文件,main.c和encrypt.c生成的zengl和encrypt可执行文件都只是libzengl.so的测试C程序 (ubuntu下也可以直接使用sudo make),当然也可以像android中那样,将zengl编译为静态库的方式,这种方式不需要root权限,而且不会和其他zengl版本相冲突,不过需要您自行调整makefile文件,作者目前只提供动态库的方式(静态库和动态库只是编译选项有所不同,源代码不需要做改动)。

    mac目录中只包含makefile文件和测试用的zengl脚本文件,所以在mac下直接make即可,需要清理中间文件时,可以使用make clean来清理。

    Android的ndk开发可以参考:http://bbs.zengl.com/thread-27-1-1.html 这篇文章(转载自51cto.com),该链接中的文章已经讲解的很详细了,有一点值得注意,就是如果要使用CDT插件对C源码进行调试的话,那么v1.3.1的zip压缩包解压后,请放置到非中文且路径中不包含空格的位置,如果路径中包含中文或包含空格的话,那么调试时,eclipse就找不到源代码,如果不想调试C源码,只是运行app的话,那就无所谓,另外转载的这篇文章中,有一个步骤是手动建立C_Builder配置,如果是已经安装了CDT的话,像作者使用的ADT一键安装包,里面的eclipse已经包含了CDT插件,那么在工程右键Android Tools中加入Android Native Support时就会自动新建一个C/C++的配置,所以这种情况下可以跳过手动新建编译配置的步骤。

    Android工程里的jni目录中存放的就是C源码和zengl导出头文件,在Android.mk中使用的是压缩包根目录linux里的源代码来编译libzengl.a静态库的,所以如果你将android工程导入到别的地方,那么在工程目录的外面同级别的目录中一定要放置linux目录,否则编译时会提示找不到zengl_main.c之类的文件。

    另外AndroidManifest.xml中的android:minSdkVersion默认是8也就是android 2.2 (对应API为8),project.properties中的target默认也是android-8,所以整个工程默认是针对android 2.2的SDK的,所以如果你不想修改这两个文件直接导入工程的话,最好安装了android 2.2的SDK,http://pan.baidu.com/share/link?shareid=2025333699&uk=1981545301 该盘对应的压缩包里面存放有2.2 api 8到4.2.2 api 17的SDK,例如2.2的SDK,解压后可以看到android-2.2_r03-linux.zip ,该zip再解压,里面可以看到一些data,images之类的目录和文件,然后在android sdk目录中例如作者的sdk安装目录为D:\adt-bundle-windows-x86-20131030\sdk ,该目录下有个platforms,在platforms中新建一个android-8目录,将前面解压的data,images之类的目录和文件都拷贝到android-8中,重启eclipse,就可以在SDK管理器和模拟器管理器中看到2.2的东东了。

    如果不安装2.2的SDK就直接导入的话,Native本地调试C源码时就会出现Unable to detect application ABI的错误。

    如果你的环境默认是android 4.4的话,例如作者下载的最新的ADT一键安装包,默认就是android 4.4 ,而且你用于调试的模拟器和手机等都是android 4.4的话,那么也可以将AndroidManifest.xml里的android:minSdkVersion改为19,project.properties里的target也改为19 ,然后再导入工程,不过如果你的手机平板等真机不是4.4的话,如果不安装对应的SDK,将只能进行java层调试,无法进行C源码调试,C调试会出现Unable to detect application ABI的错误,所以请自行测试和决定。

    如果导入工程后,在Run运行时出现如下错误 (导入默认的2.2工程时容易出现此兼容问题):


图1
 
    这是因为高版本的adt会自动为之前的2.2的工程添加一个Android Dependencing(会导致某些旧工程出现兼容问题),可以在Build Path中将其移除(如果还是不行,还可以试着把Android Private Libraries移除):


图2

    在安装好了SDK,NDK,cygwin(cygwin需要设置环境变量PATH,让其包含cygwin的bin目录),CDT插件(建议使用官方adt一键安装包,默认已经装好了SDK和CDT插件),并且经过了ndk下示例helloJni的测试后,就可以导入zengl的android工程,如果是android 2.2,可以根据需要移除Android Dependencing ,然后在eclipse中设置NDK的路径(在windows菜单的Preferences中):


图3

    接着加入Android Native Support (在RunScript工程右键中):


图4

    弹出的对话框中Library Name保持默认的runscript不变。

    然后eclipse就会切换到C/C++视图,在工程属性的C/C++ Build中设置build command:


图5

    设置NDK_DEBUG=1 ,加入ndk调试参数。

    接着就可以在RunScript工程右键中的Debug As中选择Android Application ,先让程序安装运行到真机或模拟器中,要调试C源码时,再选择Debug As中的Android Native Application 进行本地C源码调试 (选择Android Native Application之前最好都执行一下Android Application,可以避免一些不必要的错误)。

    下面是app运行的情况:


图6

    如果测试的机子上有SD卡,脚本就存放在SD卡根目录的zengl_language/scripts目录中,否则就存放在/data/data/com.zengl.runscript/scripts中。

    默认有两个脚本test.zl和test2.zl (该test2.zl脚本和linux目录中的test.zl测试RC4的脚本是一样的) ,当然也可以在文件管理器中编辑自己的脚本,然后在上图所示的输入框中输入脚本的名字,然后运行,如果有语法错误等,都会显示在运行按钮下面的TextView中。

    菜单中有三个选项:退出,关于,生成调试信息,如果选择生成调试信息,则会在scripts目录中的zengl_debuglogs.txt文件内写入调试信息(一些编译生成的AST抽象语法树信息,符号表信息,虚拟机汇编指令集,编译执行时间等)。

    百度盘和sourceforge中的zip包根目录中已经包含了一个签名过的apk,直接可以进行安装测试。

    有关ndk的调试,需要读者自己反复做测试,掌握其中的规律,即便是最新的ndk,也是有BUG的,很多错误都不能明确的表示出错误原因,需要在google论坛或stackoverflow论坛中才能找到一些相对正确的解释。

    此处android测试只做了zenglApi_Run和zenglApi_RunStr接口的测试,其实使用zenglApi_ReUse缓存机制和zenglApi_Call的组合方式应该会更好,留待以后再测试,本次就做个简单的移植性测试。

    下面看下v1.3.1所做的修改(这些信息可以在readme或linux的usage.txt中查看到,也可以直接在上面的github链接中查看到):

    zengl v1.3.1 , 增加了android工程目录,对android平台下的ARM GCC进行了测试,使用android ndk开发了一个手机上运行zengl脚本的app,arm gcc下默认约定char类型为unsigned无符号类型,所以在该平台下编译时需要指明ZL_EXP_OS_IN_ARM_GCC宏,有了该宏,ZL_CHAR类型就会被定义为signed char类型。
 
    调整了编译器和解释器中用户自定义函数的参数,例如编译器调试信息的输出函数等,添加了一个虚拟机指针参数(方便通过虚拟机指针来调用其他接口),由于增加了参数,所以在C++下可能会造成和之前版本的不兼容,需要自行调整用户函数参数。

    作者:zenglong
    时间:2013年12月24日
    官网:www.zengl.com

    该版本在zengl_global.h中对char类型的宏做了如下调整:

#ifdef ZL_EXP_OS_IN_ARM_GCC
    #define ZL_CHAR signed char //使用signed表示有符号的意思,因为ARM GCC下char默认是unsigned的(嵌入式上面会引发很多问题!),所以有必要在这里指明是signed
#else
    #define ZL_CHAR char
#endif

    在android工程下android.mk中就指定了ZL_EXP_OS_IN_ARM_GCC宏:

LOCAL_CFLAGS    := -DZL_LANG_EN_WITH_CH   -DZL_EXP_OS_IN_ARM_GCC

    此外,编译器和解释器中用户自定义函数的参数也做了调整,例如在zengl_exportPublicDefs.h中:

typedef struct _ZENGL_EXPORT_VM_MAIN_ARGS{
    ZL_EXP_INT (* userdef_info)(ZL_EXP_CHAR * infoStrPtr, ZL_EXP_INT infoStrCount, ZL_EXP_VOID * VM_ARG); //用户自定义的显示普通信息的函数,用户可以自定义信息的打印和输出方式。

.........................................................

}ZENGL_EXPORT_VM_MAIN_ARGS;

    在原来参数后面添加了个VM_ARG虚拟机指针,一共有5个自定义函数添加了这个参数,之所以将VM_ARG放在最后面,是因为可以兼容之前版本的用户C源码,但是对C++不支持,C++下需要自行对用户函数参数做调整,例如main.c中:

ZL_EXP_INT main_userdef_info(ZL_EXP_CHAR * infoStrPtr, ZL_EXP_INT infoStrCount,ZL_EXP_VOID * VM_ARG)
{
    fprintf(debuglog,"%s",infoStrPtr);
    return 0;
}

    上面是输出编译器调试信息的用户自定义函数,需要在原来基础上,在最后加个VM_ARG参数,该参数指向虚拟机指针,可以调用一些虚拟机的接口函数,例如在android工程中jni目录下的runscript.c :

ZL_EXP_INT run_print(ZL_EXP_CHAR * infoStrPtr, ZL_EXP_INT infoStrCount, ZL_EXP_VOID * VM_ARG)
{
    strPrintEnv * myenv = (strPrintEnv *)zenglApi_GetExtraData(VM_ARG,"extra");
    java_printcall(myenv,infoStrPtr);
    java_printcall(myenv,"\n");
    return 0;
}

    上面的run_print函数对应为脚本中print指令的用户自定义函数,当在脚本中执行print指令时,就会调用该函数,在该函数里,就可以通过zenglApi_GetExtraData接口和VM_ARG虚拟机指针来得到额外数据myenv结构体指针,然后就可以在java_printcall函数中使用myenv将信息输出显示到app的TextView中了。

    之前的版本一直没有这个虚拟机指针参数,所以之前的版本要在这些函数中使用虚拟机指针的话,就必须设置一个全局变量来指向虚拟机的指针,可以说是刚开始设计v1.2.0最初的嵌入式版本时没有考虑周全的地方。

    该v1.3.1版本主要是对android做个移植性的测试,所有的改动都是针对测试时发现的问题来改的。

    其他的改动请参考github中commit的diff信息。

    OK,到这里,休息,休息一下 o(∩_∩)o~~
上下篇

下一篇: zengl v1.3.2 编译静态库 Bug和向下兼容处理

上一篇: zengl v1.3.0 位运算符 字符串脚本解析 缓存 Bug修复

相关文章

zengl编程语言v0.0.5构建符号表汇编代码和虚拟机

zengl v1.7.3 获取数组之类的内存块中非NONE成员的数量

zengl v1.8.1 修复bug

zengl v1.4.1 及zengl_SDL新增的Android工程

zengl v1.7.2, zenglServer v0.2.0

zengl编程语言v0.0.11实现循环控制结构