金华市网站建设_网站建设公司_导航易用性_seo优化
2025/12/23 11:01:40 网站建设 项目流程

未测试
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)
endfunction Loop()print("call [loop] function")for k, v in ipairs({1,2,3,4,5}) doso.echo(v)end
endfunction 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,-Eifeq ($(PLAT), macosx)SHARED := -fPIC -dynamiclib -Wl,-undefined,dynamic_lookup
endifCFLAGS = -g -O2 -Wall -I$(LUA_INC)CC ?= gccLUA_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)/*.sorm -f test-vm cleanall :rm -f $(LUA_CLIB_PATH)/*.socd lua && $(MAKE) cleanrm -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语言的函数了。

 


 

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询