新建日志   展示   相册  日志列表
 

Lua调用c语言的函数

未测试
lua只识别动态库,c语言需要编译被调用模块,然后编译成动态库。

那么lua怎么识别c语言的动态库的函数呢?lua只识别以luaopen开头的函数。


 

5.4、完整示例代码
注意:在Linux上直接使用apt-get安装的lua是没有自动安装lua库的,需要下载lua的源码编译安装。

tbl.c

#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include <stdio.h>

static int
lecho (lua_State *L) {
    const char* str = lua_tostring(L, -1);
    fprintf(stdout, "%s\n", str);
    return 0;
}

static const luaL_Reg l[] = {// 导出给lua使用数组
    {"echo", lecho},
    {NULL, NULL},
};

int
luaopen_tbl_c(lua_State *L) { // local tbl = require "tbl.c"
    // 创建一张新的表,并预分配足够保存下数组 l 内容的空间
    // luaL_newlibtable(L, l);
    // luaL_setfuncs(L, l, 0);
    luaL_newlib(L, l);
    return 1;
}

 

test.lua

package.cpath = "luaclib/?.so"
local so = require "tbl.c"

function Init(args)
  print("call [init] function", args)
end

function Loop()
  print("call [loop] function")
  for k, v in ipairs({1,2,3,4,5}) do
    so.echo(v)
  end
end

function Release()
    print("call [release] function")
end

 

 


Makefile示例:
代码语言:Bash

# $@ 目标文件 $^ 所有的依赖文件 $< 第一个依赖文件
# -Wl,-E
PLAT ?= linux
# 在Makefile中,.PHONY后面的target表示的也是一个伪造的target, 而不是真实存在的文件target;
# 注意Makefile的target默认是文件。 shell
.PHONY : clean all cleanall
LUA_CLIB_PATH ?= luaclib
LUA_CLIB_SRC ?= lualib-src
# LUA_CLIB = tbl uv reg1 reg2 ud
LUA_CLIB = tbl
LUA_INC ?= ./lua/src
SHARED := -fPIC --shared
EXPORT := -Wl,-E

ifeq ($(PLAT), macosx)
    SHARED := -fPIC -dynamiclib -Wl,-undefined,dynamic_lookup
endif
    CFLAGS = -g -O2 -Wall -I$(LUA_INC)
    CC ?= gcc
    LUA_STATICLIB := lua/src/liblua.a



all : \ $(LUA_STATICLIB) \ test-vm \ $(foreach v, $(LUA_CLIB), $(LUA_CLIB_PATH)/$(v).so) $(LUA_STATICLIB) : cd lua && $(MAKE) CC='$(CC) -std=gnu99' $(PLAT) test-vm : test-vm.c $(CC) $(CFLAGS) $^ -o $@ -L$(LUA_INC) $(EXPORT) -llua -ldl -lm $(LUA_CLIB_PATH) : mkdir -p $(LUA_CLIB_PATH) $(LUA_CLIB_PATH)/tbl.so : $(LUA_CLIB_SRC)/lua-tbl.c | $(LUA_CLIB_PATH) $(CC) $(CFLAGS) $(SHARED) $^ -o $@ clean: rm -f $(LUA_CLIB_PATH)/*.so rm -f test-vm cleanall : rm -f $(LUA_CLIB_PATH)/*.so cd lua && $(MAKE) clean rm -f test-vm

 

 


5.1、原理
1. c语言编写模块,编译成动态库。
2. lua加载c语言的动态库:.so,.dll,.dylib
3. 约定读取动态库中以luaopen_*命名的函数。
4. lua获取模块对象后,通过函数名可以找到c函数地址,从而调用c代码

 


 

5.2、实现步骤

(1)c语言中实现一个函数。

static int
lecho (lua_State *L) {
    const char* str = lua_tostring(L, -1);
    fprintf(stdout, "%s\n", str);
    return 0;
}

 

(2)创建一个导出给lua使用的数组,类型是luaL_Reg。

static const luaL_Reg l[] = {// 导出给lua使用数组
    {"echo", lecho},
    {NULL, NULL},
};

 


(3)c语言实现一个luaopen开头的函数,创建一张新的表,并预分配足够保存下函数指针数组内容的空间。

int
luaopen_tbl_c(lua_State *L) { // local tbl = require "tbl.c"
    // 创建一张新的表,并预分配足够保存下数组 l 内容的空间
    // luaL_newlibtable(L, l);
    // luaL_setfuncs(L, l, 0);
    luaL_newlib(L, l);
    return 1;
}

 


(4)lua中导入c语言动态库并使用函数。

package.cpath = "luaclib/?.so"
local so = require "tbl.c"

 


(5)编译c语

 


5.3、从lua角度看调用过程
(1)lua首先会进行动态库的导入,即

local so=require "table.c"

 

(2)Lua就会去查找动态库中以luaopen_*开头的函数,*就是展开了的c文件名,比如展开为luaopen_table_c的函数名。

(3)找到函数后就执行函数,函数里面新建了一张函数地址表(函数数组),然后以table形式传给变量so。

(4)接下来就可以使用c语言的函数了。

 


 

posted @ 2025-12-23 11:00  前沿风暴  阅读(1)  评论(0)    收藏  举报

校内网 © 2004-2025

京公网安备 33010602011771号 浙ICP备2021040463号-3