跳转至

FFI


更新于 2024-01-09

Foreign Function Interface

FFI库允许纯lua代码调用c函数和结构体

ctype cdata

  • ctype是C类型的表示, 允许Lua代码与C数据类型进行交互
  • cdata一个特殊的数据类型,它表示 C 数据。
Lua
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
local ffi = require("ffi")

ffi.cdef[[
typedef struct {
    int x;
    int y;
} Point;
]]

local p = ffi.new("Point") --创建C类型的实例,得到的cdata 对象
p.x = 10
p.y = 20
print(p.x, p.y)
--输出: 10  20

local PointType = ffi.typeof("Point")
print(PointType)
--输出: ctype<struct 97>
local q = PointType()
print(q)
--输出: cdata<struct 97>: 0x7f789aed0f38

userdata

Lua调用C

Lua脚本调用C函数

Lua
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
local ffi = require("ffi") --加载FFI库
--申明
ffi.cdef[[
int printf(const char *fmt, ...);
]]
--调用c函数
ffi.C.printf("Hello %s!", "world")

local ffi = require("ffi")
ffi.cdef[[
typedef struct { double x, y; } point_t;
]]

local point
local mt = {
  __add = function(a, b) return point(a.x+b.x, a.y+b.y) end,
  __len = function(a) return math.sqrt(a.x*a.x + a.y*a.y) end,
  __index = {
    area = function(a) return a.x*a.x + a.y*a.y end,
  },
}
point = ffi.metatype("point_t", mt)

local a = point(3, 4)
print(a.x, a.y)  --> 3  4
print(#a)        --> 5
print(a:area())  --> 25
local b = a + point(0.5, 8)
print(#b)        --> 12.5

C调用lua

c语言调用lua文件

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>

int main(void) {
    lua_State *L = luaL_newstate();  /* 创建 Lua 状态机 */

    luaL_openlibs(L);  /* 打开 Lua 标准库 */

    if (luaL_loadfile(L, "script.lua") || lua_pcall(L, 0, 0, 0)) {
        /* 如果加载或执行 Lua 脚本出错,打印错误信息 */
        fprintf(stderr, "Error: %s\n", lua_tostring(L, -1));
        return 1;
    }

    lua_close(L);  /* 关闭 Lua 状态机 */
    return 0;
}

C语言调用lua,Lua调用C函数

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <stdio.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>

/* 定义一个 C 函数 */
static int my_add(lua_State *L) {
    int a = luaL_checkinteger(L, 1);  /* 从 Lua 获取第一个参数 */
    int b = luaL_checkinteger(L, 2);  /* 从 Lua 获取第二个参数 */
    lua_pushinteger(L, a + b);  /* 将结果推送到 Lua */
    return 1;  /* 返回值的数量 */
}

int main(void) {
    lua_State *L = luaL_newstate();  /* 创建 Lua 状态机 */

    luaL_openlibs(L);  /* 打开 Lua 标准库 */

    lua_register(L, "my_add", my_add);  /* 将 C 函数注册到 Lua */

    if (luaL_dostring(L, "print(my_add(10, 20))")) {
        /* 如果执行 Lua 代码出错,打印错误信息 */
        fprintf(stderr, "Error: %s\n", lua_tostring(L, -1));
        return 1;
    }

    lua_close(L);  /* 关闭 Lua 状态机 */
    return 0;
}