上次学习了怎么用C调用Lua的函数,并返回一个结果,这次看看怎么反过来,用Lua调用C的函数。
一.简介
C调用Lua函数比较简单,只需要操作相关的栈就可以了,但是Lua调用C的话,稍微有一点麻烦,虽然还是用栈来进行数据的传递,但是由于Lua中本身没有C中写的函数,所以需要多一步将C函数注册到Lua中的步骤。
Lua反过来调用C函数的话,首先,我们要写一个要被调用的函数,这个函数有一个格式的要求 ,返回值为int,但是这个int并不代表Lua函数的返回值,而是函数返回值的个数,Lua支持多重返回值,所以,在C函数中也需要支持多重返回值,但这个并不是通过return实现,而是通过将返回值压入那个万能的栈,然后返回返回值的个数。
函数原型如下:
//返回结果的个数,结果存在栈中 int 函数名(lua_State* L)
在写好函数之后,还需要将这个函数注册给Lua,否则Lua不知道这个函数。注册使用lua_register这个函数,需要给出这个函数在Lua中的函数名以及在C中的函数指针。函数原型如下:
//将C函数注册到Lua中(L, Lua中函数名,函数指针) lua_register(L, "函数名", 对应C中的函数指针);
看一个例子:
Lua程序:
--调用C的函数 print(addFunc(1, 2, 3))
C++程序:
// LuaTest.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <stdio.h> #include <windows.h> //因为Lua是C的函数,而我们的程序是C++的,所以要使用extern "C"引入头文件 extern "C"{ #include "lua.h" #include "lualib.h" #include "lauxlib.h" #include "luaconf.h" } //Lua要调用的函数(求几个数的和),注意返回值并不是结果,而是结果的个数,Lua支持多个返回值,所以就是栈中有几个返回的值。 int addFunc(lua_State* L) { double sum = 0; for (int i = 1; i <= lua_gettop(L); i++) { if (!lua_isnumber(L, i)) { lua_pushstring(L, "argument error!"); lua_error(L); } sum += lua_tonumber(L, i); } //将结果压入栈中 lua_pushnumber(L, sum); //返回结果的个数!!! return 1; } int _tmain(int argc, _TCHAR* argv[]) { //打开lua lua_State* L = luaL_newstate(); //加载lib文件 luaL_openlibs(L); //将刚才编写的C函数注册到Lua中(L, Lua中函数名,函数指针) lua_register(L, "addFunc", addFunc); //执行Lua文件 luaL_dofile(L, "test.lua"); //结束 lua_close(L); system("pause"); return 0; }
结果:
6.0
请按任意键继续. . .
其实这样调用还是比较简单的。做完编写函数和注册函数之后,Lua中就有了这个函数,我们就可以在Lua中类似库函数那样使用这个函数了。简单起见,直接dofile了一下,执行Lua文件,调用C中的函数,并将结果在Lua中打印。
要说明的是,当注册的C/C++被Lua调用时,这个C函数享有一个独有的stack,这个栈不是共有的。这个栈在进入函数体时生成,从里面索引1到n,分别放着从Lua程序中传递过来的1到n个参数,这些函数只能看到自己的栈,看不到其他栈。
二.Lua与C交互
上面的例子仅仅是C向Lua注册了个函数,Lua使用了这个函数,最后还是通过dofile整体执行的Lua文件,并没有体现到交互。下面的例子还是上面的那个函数,不过,这次只在Lua中执行一下,结果保存在Lua中的全局变量中,再使用C函数提取这个结果,在C中打印出来。这样就体现出C和Lua交互的功能。
Lua程序:
--调用C的函数,结果保存在result全局变量中,等待C提取 result = addFunc(1, 2, 3)
C++ 程序:
// LuaTest.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <stdio.h> #include <windows.h> //因为Lua是C的函数,而我们的程序是C++的,所以要使用extern "C"引入头文件 extern "C"{ #include "lua.h" #include "lualib.h" #include "lauxlib.h" #include "luaconf.h" } //Lua要调用的函数(求几个数的和),注意返回值并不是结果,而是结果的个数,Lua支持多个返回值,所以就是栈中有几个返回的值。 int addFunc(lua_State* L) { double sum = 0; for (int i = 1; i <= lua_gettop(L); i++) { if (!lua_isnumber(L, i)) { lua_pushstring(L, "argument error!"); lua_error(L); } sum += lua_tonumber(L, i); } //将结果压入栈中 lua_pushnumber(L, sum); //返回结果的个数!!! return 1; } int _tmain(int argc, _TCHAR* argv[]) { //打开lua lua_State* L = luaL_newstate(); //加载lib文件 luaL_openlibs(L); //将刚才编写的C函数注册到Lua中(L, Lua中函数名,函数指针) lua_register(L, "addFunc", addFunc); //执行Lua文件 luaL_dofile(L, "test.lua"); //Lua中返回的结果在全局变量result中,将其提取出来 lua_getglobal(L, "result"); if (!lua_isnumber(L, -1)) printf("result is not number!\n"); //在C中获得结果并打印 printf("result is %g\n", lua_tonumber(L, -1)); //结束 lua_close(L); system("pause"); return 0; }
结果:
result is 6
请按任意键继续. . .
当然,这个暂时只是一个互相调用的小例子,真正调用时需要做的可能会更加复杂,比如函数注册,包装等等。
版权声明:本文为博主原创文章,未经博主允许不得转载。