所谓FFI就是Foreign Function Interfaces。
最近的一个工作,是搞一个基于lua的开发中间件框架,希望通过lua来粘合其他厂商提供的开发库,最后统一开发接口。alien刚好能满足条件,而且体积也不大,兼容Windows和Unix系统。另外还有个C/Invoke,但是到2007年就没再更新版本了。
先从http://luaforge.net/projects/alien/下载最新版的源代码,说明文档在代码的doc目录中,比较痛苦的是,文档写的很不清楚,也没有完整的函数说明,只有看代码了。
编译完了,生成2个动态库:core.dll和struct.dll。怎么把他们搞到lua中呢?它的说明文档说,最好的方法是用LuaRocks这个工具(这个所谓的最好,应该是针对alien的作者说的)。LuaRocks是个已经编译好的Lua运行环境,提供各种外接包的管理功能,对使用lua命令行进行测试,还是很方便的。
到http://www.luarocks.org/en下载个最新版本的LuaRocks(1.0版),直接运行里面的install.bat,安装到默认目录C:\LuaRocks中。安装完后,把C:\LuaRocks\1.0设置到环境变量PATH中。在cmd中,运行luarocks install alien,自动下载alien并且安装。这时候多了2个东西,1、多了个rocks,这个目录是luarocks的扩展库目录,因为只安装了alien,因此下面只有alien目录,进如alien目录看看,基本跟自己下载alien相同;2、在bin目录下多了个constants.bat,这个工具是用来转换dll的头文件中预定义变量的,用了一下,非常不智能,不能识别#define,需要手工创建一个h文件,对源库的头文件进行引用,并且指明哪些预定义可以转换成lua变量,建议以后自己写个。
调整lua的环境变量。默认可以找到“C:\LuaRocks\1.0\lua”,如果目录不能找到,可以尝试增加 LUA_PATH=C:\LuaRocks\1.0\lua\?.lua;C:\LuaRocks\1.0\lua\?\init.lua;C:\LuaRocks\1.0\lua\?.lua;%LUA_PATH%和LUA_CPATH=C:\LuaRocks\1.0\?.dll;C:\LuaRocks\1.0\loadall.dll;%LUA_CPATH%。这2个环境变量将被require使用。luarocks的使用方法是,加参数运行lua5.1 -l luarocks.require,自动导入被安装的模块。
测试alien是否可用。进入C:\LuaRocks\rocks\alien\0.4.1-1\tests目录(当前路径很重要,因为测试文件中的代码以当前路径为基准),运行lua5.1 -l luarocks.require test_alien.lua,如果屏幕没有任何显示,说明alien运行正常。
alien在命令行的使用方式。先用lua5.1 -l luarocks.require启动lua,然后require("alien")回车,require("alien.struct")回车。如果要引入一个dll(这个dll在当前目录下),就可以直接写dll=alien.dll的名字。调用dll中的方法,需要先定义这个方法对象。例如:
>def=alien.default
>def.puts:types("int", "string")
> def.puts("foo")
foo
就是先使用default库(这个库可以在alien的代码中做修改,改成一个常用库),然后定义定义了puts函数,函数返回值为int,参数为sting。最后调用puts的过程。还是很方便的。
将alien嵌入自己的代码。可以先把它编译成lib或者dll,或者干脆嵌入源代码,然后在自己的程序里调用它的luaopen_alien_core函数初始化,就可以了。当然,需要跟lua结合使用。