Lua与C++交互初探之Lua调用C++

上一篇我们已经成功将Lua的运行环境搭建了起来,也成功在C++里调用了Lua函数。今天我来讲解一下如何在Lua里调用C++函数。

Lua作为一个轻量级脚本语言,他只包含了一些必要的系统库函数,当有需要时还得自己去写。有一次我要做一个两数异或的操作发现函数库里居然没有异或运算。不得不非常苦逼的自己去写。后来接触Lua深了之后才知道将这种"缺陷"可以由C函数来弥补。但要做到这一点对于一个对C只知道if else的学生来说确实还是有不少难度。

在学习调用的时候我也确实遇到了不少问题。一开始当然是看不懂代码,各种指针以及莫名其妙的函数,各种头大啊有木有。后来试着静下心来慢慢理了一下Hello World程序,觉得是一知半解了就把代码拷到编译器里运行一下。是的,各种报错。错得我都没信心再看下去了。

好了,上面都是一些没用的,现在开始步入正题。

Lua调用C++有两种方法:

  1. 将C函数作为应用程序的一部分
  2. 将C函数作为Lua的一个模块

这里解释一下,将C函数作为程序的一部分,就是说源文件有main方法,函数在main方法里注册,使得c函数成为Lua里的全局函数,供lua直接调用;将C函数作为Lua的一个模块。本人比较喜欢这种方式。其实是将C函数注册后封装到一个模块中,在windows系统中以dll的文件形式存在。在使用时我们只需要将他require进来就行了,另外dll文件也非常方便复制和转移,也保护了源码。所以下面将主要讲解如何将C函数注册成为Lua的模块库。记住:我之所以说是C函数,是因为函数必须以C的形式导出,因此在C++里在函数名前必须加"extern "C"";这一点下面你将会看到

下面来讲讲步骤:

    1. 在VS里新建一个VC++的win32项目(控制台应用亦可)
    2. 点击下一步选择dll(以前我们为了省事直接点了finish,这里我们得改一下后面的设置)
    3. 新建完成后配置好lua在VS里的运行环境,不会的可以看一下我的上一篇文章
    4. 输入下面代码
      // Mydll.cpp : 定义 DLL 应用程序的导出函数。
      // #include "stdafx.h"
      #include <stdio.h>
      #include <string.h>
      #include <lua.hpp>
      #include <lauxlib.h>
      #include <lualib.h> //待注册的C函数
      //需要说明的是,该函数必须以C的形式被导出,因此extern "C"是必须的。
      //定义一个求取平均数的函数
      extern "C" int average(lua_State* L)
      {
      double sum=;
      int num = lua_gettop(L);//获取参数的个数
      for (int i = ; i <= num;i++)
      sum+= lua_tonumber(L, i);
      //依次获取所有参数值,相加
      lua_pushnumber(L, sum/num);//将平均数压如栈,供lua获取 return ;//返回返回值个数,通知lua应该在栈里取几个值作为返回结果
      } extern "C" int Communicate(lua_State* L)
      {
      const char *name = lua_tostring(L, );//获取字符串
      printf("Hello %s\n", name);
      printf("I`m in C,I send a message to you");
      lua_pushstring(L, "This message from C");
      return ;
      }
      //luaL_Reg结构体的第一个字段为字符串,在注册时用于通知Lua该函数的名字。
      //第一个字段为C函数指针。
      //结构体数组中的最后一个元素的两个字段均为NULL,用于提示Lua注册函数已经到达数组的末尾。
      static luaL_Reg cMethods[] = {
      { "average", average },
      { "Communicate", Communicate },
      { 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_Mydll(lua_State* L)
      {
      const char* libName = "Mydll";
      luaL_register(L, libName, cMethods);
      return ;
      }
    5. 点击运行后我们把编译好的dll文件复制到lua解析器能找到的位置(lua文件同目录或者LUA_CPATH指向的路径一般在lua安装目录的clibs目录下)
    6. 下面编写lua测试代码
      require "Mydll"  --引入包
      
       --在调用时,必须是package.function
      
      print(Mydll.average(1.0,2.0,3.0,));
      print(Mydll.Communicate("Zack"));
    7. 测试运行

    注意他的打印顺序,因为我在Communicate函数里只向栈里压了"This message from C"这一个字符串,所以在Lua端他只向栈里取了一个元素作为返回值。还有就是注意一下在C++里面的输出,一般情况我们使用C++处理逻辑不会有输出操作,不过他的顺序没有反。下面有个很有意思的东西

    把Communicate函数提到average函数前面,结果更意外:

  C++的所有输出都放在了最后面

Lua与C++交互初探之Lua调用C++的更多相关文章

  1. Lua与C++交互初探之C++调用Lua

    Lua与C++交互初探之C++调用Lua 自从学习了lua这个脚本语言之后,无时不想着将他与c/c++联系起来,看看他真正的威力.奈何水平有限,网上找的代码无论怎样都无法运行成功.我知道是我少了某一步 ...

  2. Lua和C++交互详细总结

    转自:http://cn.cocos2d-x.org/tutorial/show?id=1474 一.Lua堆栈 要理解Lua和C++交互,首先要理解Lua堆栈. 简单来说,Lua和C/C++语言通信 ...

  3. 解释型语言和编译型语言如何交互?以lua和c为例

    转自http://my.oschina.net/mayqlzu/blog/113528 问题: 最近lua很火,因为<愤怒的小鸟>使用了lua,ios上有lua解释器?它是怎么嵌入大ios ...

  4. Lua 和 C 交互中虚拟栈的操作

    Lua 和 C 交互中虚拟栈的操作 /* int lua_pcall(lua_State *L, int nargs, int nresults, int msgh) * 以保护模式调用具有" ...

  5. 用好lua+unity,让性能飞起来——lua与c#交互篇

    前言 在看了uwa之前发布的<Unity项目常见Lua解决方案性能比较>,决定动手写一篇关于lua+unity方案的性能优化文. 整合lua是目前最强大的unity热更新方案,毕竟这是唯一 ...

  6. lua与C交互 具体

    什么样类型的函数可以被Lua调用 typedef int (*lua_CFunction) (lua_State *L); 符合类型的函数怎样处理后才可以被Lua调用 使用lua_register或者 ...

  7. Lua与C交互之基础操作(1)

    @(语言) Lua是一个嵌入式的语言,可以Lua可以作为程序库用来扩展应用的功能,也可以注册有其他语言实现的函数,这些函数可能由C语言(或其他语言)实现,可以增加一些不容易由Lua实现的功能.这就是L ...

  8. Lua和C++交互 学习记录之九:在Lua中以面向对象的方式使用C++注册的类

    主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3  参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 在 ...

  9. Lua和C++交互 学习记录之八:C++类注册为Lua模块

    主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3  参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 1 ...

随机推荐

  1. 二级路由器设置为何要关闭DHCP服务

    因为如果不关闭dhcp的话会和一级路由相冲突,你这个因该是lan口的连接法吧,如果不然的话是不需要关闭dhcp功能的路由器和路由器的连接方法有两种,一种是wan口连,一种是lan口连方法1:WAN口连 ...

  2. 二十四、Struts2中的UI标签

    二十四.Struts2中的UI标签 Struts2中UI标签的优势: 数据回显 页面布局和排版(Freemark),struts2提供了一些常用的排版(主题:xhtml默认 simple ajax) ...

  3. sqlserver同步表的脚本

    /* --同步读者 insert into [172.21.200.8].gdlisxp.dbo.读者库(借书证号,读者条码,姓名,性别,身份证号, 读者级别,级别代码,单位代码,单位,可外借,发证日 ...

  4. dataGridView 如何默认选中第一行

    datagridview默认选中第一行方法: this.dataGridView1.Rows[0].Selected = true; datagridview 去除 默认选中第一行方法:在绑定data ...

  5. http://www.shanghaihaocong.com-WORDPRESS开发的企业主题站

    wordpress是世界上使用最多的php开源博客系统,功能强大,而且拥有众多的插件,可扩展性强. 最近,我也用它做了一个企业网站,欢迎浏览:http://www.shanghaihaocong.co ...

  6. PHP-PCRE正则表达式函数

    PCRE正则表达式函数 PCRE字符类 \\b        词边界 \\d        匹配任意数字 \\s        匹配任意空白,如TAB制表符或空格 \\t        匹配一个TAB ...

  7. linux中PHP dirname(__FILE__)路径问题解决

    近期在给wordpress开发模板功能时发现,直接使用include(“文件名”)的形式调用其他php代码片段时会出现路径错误.之前服务器环境一直都是iis,未曾出现过类似的BUG,但换成linux服 ...

  8. Yii中使用PHPExcel导出Excel

    最近在研究PHP的Yii框架,很喜欢,碰到导出Excel的问题,研究了一下,就有了下面的方法: 1.首先在config/main.php中添加对PHPExcel的引用,我的方式是这样: // auto ...

  9. JAVA中ArrayList用法

    JAVA中ArrayList用法 2011-07-20 15:02:03|  分类: 计算机专业 |  标签:java  arraylist用法  |举报|字号 订阅     Java学习过程中做题时 ...

  10. 基于.NET的WebService的实现和WCF的实现

    1.新建一个MVC web项目. 2.点击项目,[右键]→[添加]→[新建项] 3.点击[Web]→[Web服务] 4.恭喜,Web Service已经新建成功,里面的方法就可以参考着根据自己的需要进 ...