打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
OSX下的LuaJIT测试


OSX下的LuaJIT测试

LuaJIT


一、安装LuaJIT

$ brew install luajit --enable-debug # 开启deubg支持

二、Hello World

2.1 main.c

#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;}

2.2 编译

$ 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

2.3 执行

$ ./a.out # Hello from Lua!

三、FFI (foreign function interface)

通过 table.foreach(ffi, print) 获取的元素表

元素 类型 说明
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

3.1 基本应用

local ffi = require 'ffi'local x = ffi.new('int')          -- 创建一个intlocal c = ffi.new('char*')        -- 创建一个char*ffi.cdef[[    int printf(const char*, ...); -- 绑定cprintf函数]]local C = ffi.CC.printf('Hello %s!/n', 'World')  -- 调用绑定好的printf函数

3.2 绑定C自定义函数

// 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.lualocal ffi = require 'ffi'ffi.cdef[[    int add(int, int);]]print('12 + 59 = ' .. ffi.C.add(12, 59))

3.3 绑定C数据结构

// main.ctypedef 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转换

3.4 技巧,生成ffi专用的类似tolua++的pkg文件

// 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'))...

3.5 绑定C++数据结构(对象)

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.Cffi.cdef[[    typedef struct Student Student;]]-- 通过gcc -E生成bindings.ffiffi.cdef(io.open('bindings.ffi', 'r'):read('*a'))local Mt_Student = {} -- metatypeMt_Student.__index = Mt_StudentMt_Student.setName = C.Student_setNameMt_Student.setAge = C.Student_setAgeMt_Student.toString = C.Student_toStringffi.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.lualocal 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(...))endlocal 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')endlocal function lfunc2()    log('lfunc2')endlocal 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 + yend)ffi.C.callLuaFunc2(cb2)cb2:free()

源码

Latest commit to the master branch on 6-28-2013
Download as zip




本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
luajit FFI LUA脚本中怎样调用C自己定义的函数
如何用C语言操作sqlite3,一文搞懂
C语言使用回调函数解决内存申请和释放的问题
剑指offer 44 翻转单词顺序列
lua和c/c 互相调用实例分析 - lxyfirst - C 博客
FLTK编程模型
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服