使c作为内嵌代码
这里我说简单的说一下这个方式,直接看代码和注视吧。
extern "C"
{
#include <lua.h>
#include<lauxlib.h>
#include <lualib.h>
};
#pragma comment(lib, "lua5.1.lib")
//待lua调用的c函数
static int getcchar(lua_State *L)
{
//压入lua的栈其实严格的来说lua的调用c的函数是通过栈来完成的
lua_pushstring(L,"I am from c");
return 1; //这里的返回值是入栈的个数
}
int main()
{
lua_State *L= luaL_newstate(); //得到lua解释器的指针
luaL_openlibs(L);//载入lua库
//注册全局函数 第二个是lua字符串第三个是函数指针
lua_register(L,"getcchar",getcchar);
luaL_dostring(L,"print(getcchar())");
lua_close(L);
return 0;
}
其实lua调用c他们之间并没有直接交互而是通过栈来交互的,当函数return过后lua就会自动释放了。
通过链接库来调用
由于我是在vs里面写的代码所以我就讲一下怎么编译成windows的链接库让lua来调用它,我们用vs新建一个dll的工程。然后也直接看代码。
#include <lua.hpp>
#pragma comment(lib, "lua5.1.lib")
//待调用c函数特别说明一下改函数必须是以extern "C" 导出的
extern "C" int add(lua_State *L)
{
if(lua_isnumber(L,1)&&lua_isnumber(L,2)) //判断一下是不是数字
lua_pushnumber(L,lua_tonumber(L,1)+lua_tonumber(L,2)); //通过栈来传递
return 1; //返回结果个数其实就是压入栈的个数
}
extern "C" int cgetchar(lua_State *L)
{
lua_pushstring(L,"hell lua i am c"); //压入栈
return 1;
}
//luaL_Reg结构体的第一个字段为字符串,在注册时用于通知Lua该函数的名字。
//第一个字段为C函数指针。
//结构体数组中的最后一个元素的两个字段均为NULL,用于提示Lua注册函数已经到达数组的末尾。
static luaL_Reg libs[] = {
{"add", add},
{"cgetchar",cgetchar},
{NULL, NULL}
};
//该C库的唯一入口函数。其函数签名等同于上面的注册函数。见如下几点说明:
//1. 我们可以将该函数简单的理解为模块的工厂函数。
//2. 其函数名必须为luaopen_xxx,其中xxx表示library名称。Lua代码require "xxx"需要与之对应。
//3. 在luaL_register的调用中,其第一个字符串参数为模块名"xxx",第二个参数为待注册函数的数组。
//4. 需要强调的是,所有需要用到"xxx"的代码,不论C还是Lua,都必须保持一致,这是Lua的约定,
// 否则将无法调用。
extern "C" __declspec(dllexport)
int luaopen_luacdll(lua_State* L)
{
const char* libName = "luacdll";
luaL_register(L,libName,libs);
return 1;
}
然后我们编译出dll链接库,拷贝到lua的安装目录下我的是E:\Lua\5.1\clibs这个目录下面然后我们写入lua代码然后看结果。
a=require"luacdll"
print(a.add(3,10))
print(a.cgetchar())
结果是
13
hell lua i am c