内容简介:===
=
=
=
lua编程之 lua 与C相互调用 https://www.cnblogs.com/coderkian/p/4057750.html
lua是扩展性非常良好的语言,虽然核心非常精简,但是用户可以依靠lua库来实现大部分工作。除此之外,lua还可以通过与C函数相互调用来扩展程序功能。在C中嵌入lua脚本既可以让用户在不重新编译代码的情况下修改lua代码更新程序,也可以给用户提供一个自由定制的接口,这种方法遵循了机制与策略分离的原则。在lua中调用C函数可以提高程序的运行效率。lua与C的相互调用在工程中相当实用,本文就来讲解lua与C相互调用的方法。
Lua与C相互调用的首要问题是如何交换数据,lua API使用了一个抽象的栈与 C语言 交换数据,提供了压入元素,查询元素和弹出元素等功能的API操作栈, 这里 可以查看lua5.2中每个函数的详细文档,栈中的元素可以通过索引访问,从栈底向上是从1开始递增的正整数,从栈顶向下是从-1开始递减的负整数,栈的元素按照FIFO的规则进出。
一、 C 调用 lua
先通过一个简单的例子了解C是怎么调用lua的,
//test.lua
width = 10
height = 20
//test.c
#include <stdio.h>
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
int main() {
lua_State *L = luaL_newstate();
luaL_openlibs(L);
if(luaL_loadfile(L, "test.lua") || lua_pcall(L, 0,0,0)){
printf("error %s\n", lua_tostring(L,-1));
return -1;
}
lua_getglobal(L,"width");
lua_getglobal(L,"length");
printf("width = %d\n", lua_tointeger(L,-2));
printf("length = %d\n", lua_tointeger(L,-1));
lua_close(L);
return 0;
}
luaL_newstate创建一个新的lua_State,C和lua的所有操作都要依赖这个lua环境, luaL_openlibs将lualib.h中定义的lua标准库加载到进lua_State。
luaL_loadfile从文件中加载lua代码并编译,编译成功后的程序块被压入栈中,
lua_pcall会将程序块弹出并在保护模式下解释执行。代码中调用lua_pcall就在lua_State中定义了 width和 length两个全局变量。
lua_getglobal将全局变量的值压入栈中,width先入栈,在-2的位置,length在栈顶。
除了变量,C代码还可以直接调用lua中定义的函数
//test.lua
function add(x, y)
return x+y
end
//test.c
#include <stdio.h>
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include <math.h>
int main() {
lua_State *L = luaL_newstate();
luaL_openlibs(L);
if(luaL_loadfile(L, "test.lua") || lua_pcall(L, 0,0,0)){
printf("error %s\n", lua_tostring(L,-1));
return -1;
}
lua_getglobal(L,"add");
lua_pushnumber(L, 10);
lua_pushnumber(L, 20);
if(lua_pcall(L, 2, 1, 0) != 0){
printf("error %s\n", lua_tostring(L,-1));
return -1;
}
double z = lua_tonumber(L, -1);
printf("z = %f \n", z);
lua_pop(L, 1);
lua_close(L);
return 0;
}
lua_pcall(L, 2, 1, 0)表示,传入两个参数,期望得到一个返回值,0表示错误处理函数在栈中的索引值,压入结果前会弹出函数和参数,所以z的索引是-1.
二、 lua 调用 C
lua可以将C函数注册到lua中,C函数必须遵循统一的原型,这个原型定义在lua.h中,
typedef int (*) (lua_State *)
用C函数扩展lua时,一般将所有的C函数编译成一个独立的模块,方便增加新的函数。
//mylib.c
#include <stdio.h>
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include <math.h>
static int myadd(lua_State *L){
int a = luaL_checknumber(L, 1);
int b = luaL_checknumber(L, 2);
lua_pushnumber(L, a+b);
return 1;
}
static const struct luaL_Reg mylib [] = {
{"add", myadd},
{NULL, NULL}
};
int luaopen_mylib(lua_State *L){
luaL_newlib(L, mylib);
return 1;
}
//call.lua
#!/usr/local/bin/lua
lib=require "mylib"
print(lib.add(1, 2))
每个被lua调用的C函数都有自己的私有栈,压入参数的索引从1开始递增,结果值也是直接压入栈中,函数返回时会将压入的参数全部删除,只留下结果值。mylib[]声明了模块中所有C函数列表,每一项映射了C函数在lua中的命名,比如上面代码中myadd函数在lua中用add表示,列表必须用{NULL, NULL}结束。 luaL_newlib在栈中创建一个table,将mylib数组中的C函数注册进这个table中。 luaopen_mylib将这个table中的函数加载进lua环境中。
先将C代码编译成动态链接库,
gcc -shared -fPIC -o mylib.so mylib.c -llua -lm -ldl
lua代码中,require会查找 mylib.so,并调用该链接库中的 luaopen_mylib,luaopen_的后缀必须与动态链接库名字一样,这是由require查找函数方式决定的。
=
=
=
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Windows核心编程(第5版)
Jeffrey Richter、Christophe Nasarre / 葛子昂、周靖、廖敏 / 清华大学出版社 / 2008-9 / 99.00元
这是一本经典的Windows核心编程指南,从第1版到第5版,引领着数十万程序员走入Windows开发阵营,培养了大批精英。. 作为Windows开发人员的必备参考,本书是为打算理解Windows的C和C++程序员精心设计的。第5版全面覆盖Windows XP,Windows Vista和Windows Server 2008中的170个新增函数和Windows特性。书中还讲解了Windows......一起来看看 《Windows核心编程(第5版)》 这本书的介绍吧!