OSX下安装zeromq
30 Mar 2013一、安装
$ brew install zeromq
此处省略N个字...
LANG="en_US.UTF-8"
###### http://repogen.simplylinux.ch/index.php ###### Ubuntu Main Repos deb http://cn.archive.ubuntu.com/ubuntu/ quantal main deb-src http://cn.archive.ubuntu.com/ubuntu/ quantal main ###### Ubuntu Update Repos deb http://cn.archive.ubuntu.com/ubuntu/ quantal-security main deb http://cn.archive.ubuntu.com/ubuntu/ quantal-updates main deb http://cn.archive.ubuntu.com/ubuntu/ quantal-proposed main deb http://cn.archive.ubuntu.com/ubuntu/ quantal-backports main deb-src http://cn.archive.ubuntu.com/ubuntu/ quantal-security main deb-src http://cn.archive.ubuntu.com/ubuntu/ quantal-updates main deb-src http://cn.archive.ubuntu.com/ubuntu/ quantal-proposed main deb-src http://cn.archive.ubuntu.com/ubuntu/ quantal-backports main
$ brew install luajit --enable-debug # 开启deubg支持
#include "lua.h" #include "lualib.h" #include "lauxlib.h" int main(void) { lua_State* L = luaL_newstate(); luaL_openlibs(L); luaL_dostring(L, "return 'Hello from Lua!'"); // 执行Lua语句 const char * str = lua_tostring(L, -1); // 获取Lua语句的返回值 printf(str); lua_close(L); return 0; }
$ gcc-4.7 \ -lluajit-5.1 \ # 加入luajit-5.1的库 -I/usr/local/include/luajit-2.0 \ # 加入头文件搜索路径,因为系统已经装有lua会有冲突 -pagezero_size 10000 \ # 64位的OSX的一个bug -image_base 100000000 \ # 详细说明在 http://luajit.org/install.html main.c
$ ./a.out # Hello from Lua!
通过 @table.foreach(ffi, print)@ 获取的元素表
table(table table-bordered). |_.元素|_.类型|_.说明| |new|function|创建C数据类型 @cpoint = ffi.new('Point', {23, 89})@| |cast|function|转换成C数据类型 @cint = ffi.cast('int', 123)@| |typeof|function|创建给定的C数据类型 @cdouble = ffi.typeof('double')@| |sizeof|function|| |alignof|function|| |istype|function|| |fill|function|| |cdef|function|绑定C函数 @ffi.cdef[[ int printf(const char*, ...); ]]@| |abi|function|| |metatype|function|| |copy|function|| |errno|function|| |load|function|| |arch|x64|当前CPU架构| |string|function|| |gc|function|| |os|OSX|当前系统|| |C|userdata|| |offsetof|function|| see more: "http://luajit.org/ext_ffi_api.html":http://luajit.org/ext_ffi_api.htmllocal ffi = require 'ffi' local x = ffi.new('int') -- 创建一个int local c = ffi.new('char*') -- 创建一个char* ffi.cdef[[ int printf(const char*, ...); -- 绑定c的printf函数 ]] local C = ffi.C C.printf('Hello %s!/n', 'World') -- 调用绑定好的printf函数
// main.c #include "lua.h" #include "lualib.h" #include "lauxlib.h" int add(int, int); int main(void) { lua_State* L = luaL_newstate(); luaL_openlibs(L); luaL_dofile(L, "main.lua"); lua_close(L); return 0; } int add(int x, int y) { return x + y; }
// main.lua local ffi = require 'ffi' ffi.cdef[[ int add(int, int); ]] print('12 + 59 = ' .. ffi.C.add(12, 59))
// main.c typedef struct { char *name; int age; } Student; void call(Student*); // 打印这个对象 ...
// main.lua ... ffi.cdef[[ typedef struct { char *name; int age; } Student; void call(Student*); ]] C.call(ffi.new('Student', {ffi.cast('char*', 'tom'), 23)}) -- 注意char*需要使用cast转换
// stub.c #include "header.h" // 创建stub.c,只包含要绑定的头文件
$ gcc-4.7 -E stud.c | grep -v '^#' > ffi_header.h
// main.lua ... ffi.cdef(io.open('ffi_header.h', 'r'):read('*a')) ...
@Student.h@
#ifndef __STUDENT_H__ #define __STUDENT_H__ class Student { public: Student(); ~Student(); void toString(void); void setName(const char* name); void setAge(int age); private: char* name; int age; }; #endif
@Student.cpp@
#include "Student.h" Student::Student() { } Student::~Student() { } void Student::toString() { std::cout << "name: " << name << " age: " << age << std::endl; } void Student::setName(const char* name) { delete this->name; this->name = new char[strlen(name) + 1]; strcpy(this->name, name); } void Student::setAge(int age) { this->age = age; }
@bindings.h@
#ifndef __BINDINGS_H__ #define __BINDINGS_H__ // Student对象提供给Lua的接口 Student* Student_new(void); void Student_toString(Student*); void Student_setName(Student*, const char*); void Student_setAge(Student*, int); void Student__gc(Student*); #endif
@bindings.cpp@
#include "Student.h" extern "C" { #include "bindings.h" } extern "C" { Student* Student_new(void) { return new Student(); } void Student_toString(Student* stu) { stu->toString(); } void Student_setName(Student* stu, const char* name) { stu->setName(name); } void Student_setAge(Student* stu, int age) { stu->setAge(age); } void Student__gc(Student* stu) { delete stu; } }
@main.lua@
local ffi = require 'ffi' local C = ffi.C ffi.cdef[[ typedef struct Student Student; ]] -- 通过gcc -E生成bindings.ffi ffi.cdef(io.open('bindings.ffi', 'r'):read('*a')) local Mt_Student = {} -- metatype Mt_Student.__index = Mt_Student Mt_Student.setName = C.Student_setName Mt_Student.setAge = C.Student_setAge Mt_Student.toString = C.Student_toString ffi.metatype('Student', Mt_Student) local stu = ffi.gc(C.Student_new(), C.Student__gc) stu:setName("tom") stu:setAge(23) stu:toString()
@generate_ffi.lua@ 生成 @bindings.ffi@
-- 执行 -- $ luajit generate_ffi.lua local stub = io.open("stub.c", "w") stub:write([[#include "bindings.h"]]) stub:close() os.execute([[gcc -I . -E -P stub.c > bindings.ffi]]) os.execute([[rm stub.c]]) print 'done'
build
$ g++ \ -lluajit-5.1 \ -I/usr/local/include/luajit-2.0 \ -pagezero_size 10000 \ -image_base 100000000 \ -o maincpp \ main.cpp Student.cpp bindings.cpp $ ./maincpp
@student.dylib@ 加载动态库并绑定
$ g++ -c Student.cpp bindings.cpp # 生成Student.o bindings.o $ g++ -dynamiclib Student.o bindings.o -o libstudent.dylib # 生成动态库 $ g++ \ -lluajit-5.1 \ -I/usr/local/include/luajit-2.0 \ -pagezero_size 10000 \ -image_base 100000000 \ -o maincpp \ main.cpp
@$ vim main.lua@
- --local C = ffi.C + local C = ffi.load('student')
@$ ./maincpp@
@testcallback.c@ 首先要明白函数指针
#include "lua.h" #include "lualib.h" #include "lauxlib.h" typedef void (*Callback)(void); // 定义一个无参无返回值的函数指针类型 typedef int (*Callback2)(int,int); // 定义一个接收两个参数int返回值的函数指针类型 void callLuaFunc(Callback); void callLuaFunc2(Callback2); Callback callbackFunc = NULL; Callback2 callbackFunc2 = NULL; // 函数指针变量例子 void MyFunc(int); // 普通函数 void (*MyFuncP)(int); // 函数指针变量MyFuncP,注意有typedef与没有的区别 void MyFunc(int x) { printf("x = %d\n", x); } int main(void) { MyFuncP = &MyFunc; // 把普通函数的地址赋给MyFuncP函数指针变量 MyFuncP(12); // 通过函数指针调用普通函数 lua_State* L = luaL_newstate(); luaL_openlibs(L); luaL_dofile(L, "luascripts/testcallback.lua"); lua_close(L); return 0; } void callLuaFunc(Callback cb) { callbackFunc = cb; callbackFunc(); } void callLuaFunc2(Callback2 cb2) { callbackFunc2 = cb2; int count = callbackFunc2(12, 46); printf("count: %d\n", count); }
@testcallback.lua@ ffi的回调机制
local log = function(...) print('[LuaJIT] -- ' .. string.format(...)) end local ffi = require 'ffi' ffi.cdef[[ typedef void (*Callback)(void); typedef int (*Callback2)(int,int); void callLuaFunc(Callback); void callLuaFunc2(Callback2); ]] local function lfunc() log('lfunc') end local function lfunc2() log('lfunc2') end local cb = ffi.cast('Callback', lfunc); -- 把lua函数转换成c函数指针 ffi.C.callLuaFunc(cb) -- 把转换后的c函数指针传递给c函数 cb:set(lfunc2); -- 修改回调函数 ffi.C.callLuaFunc(cb) cb:free() local cb2 = ffi.cast('Callback2', function(x, y) log(x .. ' + ' .. y .. ' = ' .. x + y) return x + y end) ffi.C.callLuaFunc2(cb2) cb2:free()
</br>源码
class vector { TOLUA_TEMPLATE_BIND(T, string, CCSprite*) // 添加我们想要的容器类型 void clear(); int size() const; const T& operator[](int index) const; T& operator[](int index); void push_back(T val); vector(); ~vector(); };
... #ifdef __cplusplus tolua_cclass(tolua_S,"vector_CCSprite__","vector<CCSprite*>","",tolua_collect_vector_CCSprite__); #else tolua_cclass(tolua_S,"vector_CCSprite__","vector<CCSprite*>","",NULL); #endif tolua_beginmodule(tolua_S,"vector_CCSprite__"); tolua_function(tolua_S,"clear",tolua_Lottery_vector_CCSprite___clear00); tolua_function(tolua_S,"size",tolua_Lottery_vector_CCSprite___size00); tolua_function(tolua_S,".geti",tolua_Lottery_vector_CCSprite____geti00); tolua_function(tolua_S,".seti",tolua_Lottery_vector_CCSprite____seti00); tolua_function(tolua_S,".geti",tolua_Lottery_vector_CCSprite____geti01); tolua_function(tolua_S,"push_back",tolua_Lottery_vector_CCSprite___push_back00); tolua_function(tolua_S,"new",tolua_Lottery_vector_CCSprite___new00); tolua_function(tolua_S,"new_local",tolua_Lottery_vector_CCSprite___new00_local); tolua_function(tolua_S,".call",tolua_Lottery_vector_CCSprite___new00_local); tolua_function(tolua_S,"delete",tolua_Lottery_vector_CCSprite___delete00); tolua_endmodule(tolua_S); ...
local string_vector = vector_string_:new_local() string_vector:push_back("hello") string_vector:push_back("world") cclog(string_vector[0].." "..string_vector[1]) local ccsprite_vector = vector_CCSprite__:new_local() // 注意指针类型的是__ ccsprite_vector:push_back(CCSprite:create("image")) ccsprite_vector:push_back(CCSprite:create("image"))
#ifndef __LUAHANDLER_H__ #define __LUAHANDLER_H__ #include "CCLuaEngine.h" class LuaHandler { public: LuaHandler(): m_nLuaHandler(0){} virtual ~LuaHandler(){} // 注册Lua回调函数 virtual void registerLuaHandler(int nHandler) { unregisterLuaHandler(); m_nLuaHandler = nHandler; LUALOG("[LUA] Add lua handler: %d", m_nLuaHandler); } // 取消注册 virtual void unregisterLuaHandler(void) { if (m_nLuaHandler != 0) { cocos2d::CCScriptEngineManager::sharedManager() ->getScriptEngine() ->removeScriptHandler(m_nLuaHandler); m_nLuaHandler = 0; LUALOG("[LUA] Remove lua handler: %d", m_nLuaHandler); } } // 获取在Lua中注册的Lua回调函数引用 int getLuaHandler() { return m_nLuaHandler; }; // 获取Lua的堆,方法调用各种函数 cocos2d::CCLuaStack *getLuaStack(void) { cocos2d::CCLuaEngine *pEngine = (cocos2d::CCLuaEngine*) (cocos2d::CCScriptEngineManager::sharedManager()->getScriptEngine()); return pEngine->getLuaStack(); } protected: int m_nLuaHandler; }; #endif
#include "LuaHandler.h" class MyLayer: public CCLayer, public LuaHandler { public: // ... 省略 void callback(void) { int mHandler = getLuaHandler(); if (mHandler != 0) { CCLuaStack *pStack = getLuaStack(); pStack->pushInt(1234); // 回调函数第一个参数 pStack->pushString("abc"); // 回调函数第二个参数 pStack->executeFunctionByHandler(mHandler, 2); // 2表示回调函数有两个参数 } } };
class MyLayer: public CCLayer { // ... 省略 void registerLuaHandler(LUA_FUNCTION mHandler); void unregisterLuaHandler(void); };
local function callback(f, t) cclog("第一个参数:" .. f .. ",第二个参数:" .. t) end local myLayer = MyLayer:create() myLayer:registerLuaHandler(callback) -- 注册回调函数 myLayer:unregisterLuaHandler() -- 取消注册