本文最后更新于 38 天前,其中的信息可能已经有所发展或是发生改变。
Lua调用C的几种主流方法
- 封装成c动态链接库,在
lua中require - 通过在
C中注册函数给lua调用 - 在
LuaJIT里面可以使用ffi高性能的调用C
调用C动态库
将C函数封装成动态库,通过luaL_newlib 将C 函数打包成一个 Lua 模块,以供 Lua 脚本使用
创建文件并保持格式如下
.
| Makefile
| test.lua
|
+---inc
| luaLib.h
|
\---src
cFuntion.c
luaLib.c
文件内容如下
test.lua
--设置.so搜寻路径,若动态库与lua文件在同一目录下则无需指定
--package.cpath = "./?.so"
local myLib = require "mylib"
local add
myLib.printDemo()
add = myLib.addDemo(1, 12)
print(add)
Makefile
CC := gcc
SRCS := $(wildcard ./src/*.c)
OBJS := $(SRCS:.c=.o)
INC_DIR = -I ./inc/
CFLAGS := -Wall -fPIC
# 使用 pkg-config 自动探测 LUA_PKG(仍支持外部覆盖)
PKG_CONFIG ?= pkg-config
LUA_CANDIDATES := lua5.4 lua5.3 lua5.2 luajit lua
LUA_PKG ?= $(firstword $(foreach m,$(LUA_CANDIDATES),$(if $(shell $(PKG_CONFIG) --exists $(m) && echo yes),$(m))))
ifeq ($(strip $(LUA_PKG)),)
$(error 未找到可用的 Lua 开发包,请安装 liblua5.x-dev 或手动设置 LUA_PKG=lua5.4 等)
endif
$(info Using LUA_PKG=$(LUA_PKG))
PKG_CFLAGS := $(shell $(PKG_CONFIG) --cflags $(LUA_PKG))
PKG_LIBS := $(shell $(PKG_CONFIG) --libs $(LUA_PKG))
PRODUCT := mylib.so
all: $(PRODUCT)
$(PRODUCT): $(OBJS)
$(CC) -shared -o $@ $^ $(PKG_LIBS)
src/%.o: src/%.c
$(CC) -c $< -o $@ $(CFLAGS) $(INC_DIR) $(PKG_CFLAGS)
.PHONY: clean
clean:
rm -f $(PRODUCT) $(OBJS)
luaLib.h
#ifndef __MYLIB_H__
#define __MYLIB_H__
#include <lua.h>
#include <lauxlib.h>
int luaLibAdd(int a, int b);
int luaLibPrint();
#endif
cFunction.c
#include <stdio.h>
#include "luaLib.h"
/**
* 定义在lua中可调用的函数,要遵循规范:返回值必须为int,需传入lua_State
*/
int luaLibAdd(int a, int b)
{
return a + b;
}
int luaLibPrint()
{
char *str = "lua calls the C function demo";
printf("%s\n", str);
return 0;
}
luaLib.c
#include <stdio.h>
#include "luaLib.h"
/**
* 定义在lua中可调用的函数,要遵循规范:返回值必须为int,需传入lua_State
*/
int addDemo(lua_State *L)
{
int num_a = luaL_checkinteger(L, 1);
int num_b = luaL_checkinteger(L, 2);
int num_c;
num_c = luaLibAdd(num_a, num_b);
lua_pushnumber(L, num_c);
return 1;
}
int printDemo(lua_State *L)
{
luaLibPrint();
return 0;
}
int luaopen_mylib(lua_State *L)
{
luaL_Reg Clib[] =
{
{"addDemo", addDemo},
{"printDemo", printDemo},
{NULL, NULL}
};
luaL_newlib(L, Clib);
return 1;
}
运行结果

通过在C中注册函数给lua调用
程序主体在C中运行,C函数注册到Lua中。C调用Lua,Lua调用C注册的函数,C得到函数的执行结果
创建文件并保持格式如下
.
demo.c
Makefile
文件内容如下
demo.c
#include <stdio.h>
#include <stdlib.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
int addDemo(lua_State *L)
{
int num_a = luaL_checkinteger(L, 1);
int num_b = luaL_checkinteger(L, 2);
int num_c = num_a + num_b;
lua_pushnumber(L, num_c);
return 1;
}
int main(void)
{
lua_State *L = luaL_newstate(); // 创建Lua状态机。
luaL_openlibs(L); // 打开Lua状态机"L"中的所有Lua标准库。
lua_pushcfunction(L, addDemo);
lua_setglobal(L, "addDemo"); // 弹出栈顶元素,并在Lua中用名为"addDemo"的全局变量存储。
const char* testfunc = "add = addDemo(1,2);print(\"add =\",add)";
if(luaL_dostring(L, testfunc)) {
printf("Failed to invoke.\n");
}
lua_close(L); // 关闭Lua状态机。
return 0;
}
Makefile
CC := gcc
SRCS := $(wildcard *.c)
OBJS := $(SRCS:.c=.o)
CFLAGS := -g -Wall
PRODUCT := a.out
# 使用 pkg-config 自动探测 LUA_PKG(仍支持外部覆盖)
PKG_CONFIG ?= pkg-config
LUA_CANDIDATES := lua5.4 lua5.3 lua5.2 luajit lua
LUA_PKG ?= $(firstword $(foreach m,$(LUA_CANDIDATES),$(if $(shell $(PKG_CONFIG) --exists $(m) && echo yes),$(m))))
ifeq ($(strip $(LUA_PKG)),)
$(error 未找到可用的 Lua 开发包,请安装 liblua5.x-dev 或手动设置 LUA_PKG=lua5.4 等)
endif
$(info Using LUA_PKG=$(LUA_PKG))
PKG_CFLAGS := $(shell $(PKG_CONFIG) --cflags $(LUA_PKG))
PKG_LIBS := $(shell $(PKG_CONFIG) --libs $(LUA_PKG))
all: $(PRODUCT)
$(PRODUCT): $(OBJS)
$(CC) -o $@ $^ $(PKG_LIBS)
%.o: %.c
$(CC) -c $< -o $@ $(CFLAGS) $(PKG_CFLAGS)
.PHONY: clean
clean:
$(RM) -f $(PRODUCT) $(OBJS)
运行结果
