Lua调用自定义C模块

 更新时间:2015年09月24日 09:47:54   投稿:hebedich  
Lua可以调用C函数的能力将极大的提高Lua的可扩展性和可用性。对于有些和操作系统相关的功能,或者是对效率要求较高的模块,我们完全可以通过C函数来实现,之后再通过Lua调用指定的C函数。对于那些可被Lua调用的C函数而言,其接口必须遵循Lua要求的形式
(福利推荐:【腾讯云】服务器最新限时优惠活动,云服务器1核2G仅99元/年、2核4G仅768元/3年,立即抢购>>>:9i0i.cn/qcloud

(福利推荐:你还在原价购买阿里云服务器?现在阿里云0.8折限时抢购活动来啦!4核8G企业云服务器仅2998元/3年,立即抢购>>>:9i0i.cn/aliyun

这是《Lua程序设计》中提到的,但是想成功执行,对于初学Lua的确没那么简单。这里涉及如何如何生成一个动态链接库so文件;Lua5.2中导出函数从LuaL_register变成了LuaL_newlib。对于具体的细节有待深入。这里的模块名是hello_lib, Lua解释器会根据名字找到对应的模块,而后执行其中的 luaopen_XXX方法。 代码:

#include <math.h>
#include <lua5.2/lua.h>
#include <lua5.2/lauxlib.h>
#include <lua5.2/lualib.h>
static int hello_sin(lua_State *L){
double d = luaL_checknumber(L, 1);
lua_pushnumber(L, sin(d));
return 1;
}
static const struct luaL_Reg hello_lib[] = {
{"hello_sin" , hello_sin},
{NULL, NULL}
};
int luaopen_hello_lib(lua_State *L){
luaL_newlib(L, hello_lib);
//luaL_register(L, "hello_lib",hello_lib); // lua 5.1
return 1;
}

在Lua中调用:

local hello = require "hello_lib"
print(hello.hello_sin(1))

执行过程和结果: 

1. C函数作为应用程序的一部分。

#include <stdio.h>
#include <string.h>
#include <lua.hpp>
#include <lauxlib.h>
#include <lualib.h>

//待Lua调用的C注册函数。
static int add2(lua_State* L)
{
  //检查栈中的参数是否合法,1表示Lua调用时的第一个参数(从左到右),依此类推。
  //如果Lua代码在调用时传递的参数不为number,该函数将报错并终止程序的执行。
  double op1 = luaL_checknumber(L,1);
  double op2 = luaL_checknumber(L,2);
  //将函数的结果压入栈中。如果有多个返回值,可以在这里多次压入栈中。
  lua_pushnumber(L,op1 + op2);
  //返回值用于提示该C函数的返回值数量,即压入栈中的返回值数量。
  return 1;
}

//另一个待Lua调用的C注册函数。
static int sub2(lua_State* L)
{
  double op1 = luaL_checknumber(L,1);
  double op2 = luaL_checknumber(L,2);
  lua_pushnumber(L,op1 - op2);
  return 1;
}

const char* testfunc = "print(add2(1.0,2.0)) print(sub2(20.1,19))";

int main()
{
  lua_State* L = luaL_newstate();
  luaL_openlibs(L);
  //将指定的函数注册为Lua的全局函数变量,其中第一个字符串参数为Lua代码
  //在调用C函数时使用的全局函数名,第二个参数为实际C函数的指针。
  lua_register(L, "add2", add2);
  lua_register(L, "sub2", sub2);
  //在注册完所有的C函数之后,即可在Lua的代码块中使用这些已经注册的C函数了。
  if (luaL_dostring(L,testfunc))
    printf("Failed to invoke.\n");
  lua_close(L);
  return 0;
}

2. C函数库成为Lua的模块。

    将包含C函数的代码生成库文件,如Linux的so,或Windows的DLL,同时拷贝到Lua代码所在的当前目录,或者是LUA_CPATH环境变量所指向的目录,以便于Lua解析器可以正确定位到他们。在我当前的Windows系统中,我将其copy到"C:\Program Files\Lua\5.1\clibs\",这里包含了所有Lua可调用的C库。见如下C语言代码和关键性注释:

 #include <stdio.h>
 #include <string.h>
 #include <lua.hpp>
 #include <lauxlib.h>
 #include <lualib.h>
 
 //待注册的C函数,该函数的声明形式在上面的例子中已经给出。
 //需要说明的是,该函数必须以C的形式被导出,因此extern "C"是必须的。
 //函数代码和上例相同,这里不再赘述。
 extern "C" int add(lua_State* L) 
 {
   double op1 = luaL_checknumber(L,1);
   double op2 = luaL_checknumber(L,2);
   lua_pushnumber(L,op1 + op2);
   return 1;
 }
 
 extern "C" int sub(lua_State* L)
 {
   double op1 = luaL_checknumber(L,1);
   double op2 = luaL_checknumber(L,2);
   lua_pushnumber(L,op1 - op2);
   return 1;
 }
 
 //luaL_Reg结构体的第一个字段为字符串,在注册时用于通知Lua该函数的名字。
 //第一个字段为C函数指针。
 //结构体数组中的最后一个元素的两个字段均为NULL,用于提示Lua注册函数已经到达数组的末尾。
 static luaL_Reg mylibs[] = { 
   {"add", add},
   {"sub", sub},
   {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_mytestlib(lua_State* L) 
 {
   const char* libName = "mytestlib";
   luaL_register(L,libName,mylibs);
   return 1;
 }

    见如下Lua代码:

require "mytestlib"  --指定包名称

--在调用时,必须是package.function

print(mytestlib.add(1.0,2.0))
print(mytestlib.sub(20.1,19))

相关文章

  • Lua中调用C++函数示例

    Lua中调用C++函数示例

    这篇文章主要介绍了Lua中调用C++函数示例,本文给出的C++函数average()演示了如何接受多个参数且返回超过一个值,需要的朋友可以参考下
    2015-07-07
  • Lua脚本语言入门笔记

    Lua脚本语言入门笔记

    这篇文章主要介绍了Lua脚本语言入门笔记,本文讲解了什么是Lua、Lua里的注释、Lua里的变量、Lua里的运算符、Lua里的数据类型、Lua里的代码块、Lua里的关系类型、Lua里的函数、Lua里的类等内容,需要的朋友可以参考下
    2014-12-12
  • Lua中的函数写法简明示例

    Lua中的函数写法简明示例

    这篇文章主要介绍了Lua中的函数写法简明示例,本文是一篇个人学习笔记,简单的记录了Lua函数的写法,需要的朋友可以参考下
    2015-04-04
  • Lua基础之运算符的使用示例

    Lua基础之运算符的使用示例

    今天小编就为大家分享一篇关于Lua基础之运算符的使用示例,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-12-12
  • Lua脚本调用外部脚本

    Lua脚本调用外部脚本

    在游戏脚本开发中,我们往往会发现脚本量非常大,而且我们经常会在一些核心脚本文件中定义常用的功能函数,但是Lua脚本没有提供include关键词,那又是怎样调用外部函数的呢?如何实现脚本的Include功能?
    2014-09-09
  • Lua中的捕获机制和转换技巧介绍

    Lua中的捕获机制和转换技巧介绍

    这篇文章主要介绍了Lua中的捕获机制和转换技巧介绍,捕获是这样一种机制:可以使用模式串的一部分匹配目标串的一部分,将你想捕获的模式用圆括号括起来,就指定了一个捕获,需要的朋友可以参考下
    2014-11-11
  • Lua中遍历数组和table的4种方法

    Lua中遍历数组和table的4种方法

    这篇文章主要介绍了Lua中遍历数组和table的4种方法,本文讲解了使用for遍历、迭代器的方式遍历等方法,同时提供一个复杂table的的遍历方法,需要的朋友可以参考下
    2015-04-04
  • Lua中数字for循环实例

    Lua中数字for循环实例

    这篇文章主要介绍了Lua中数字for循环实例,本文直接给出数字循环代码示例,并探讨了改变控制变量的一些问题,需要的朋友可以参考下
    2015-04-04
  • Lua中rawset和rawget的作用浅析

    Lua中rawset和rawget的作用浅析

    这篇文章主要介绍了Lua中rawset和rawget的作用浅析,本文分别用两段代码演示了rawset和rawget的作用,需要的朋友可以参考下
    2015-04-04
  • Lua中的闭包小结

    Lua中的闭包小结

    这篇文章主要介绍了Lua中的闭包小结,本文对闭包的概念做了讲解,同时给出闭包代码示例,需要的朋友可以参考下
    2014-09-09

最新评论

?


http://www.vxiaotou.com