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. Linux下的”锁“事儿

    原由 之所以写这篇文章当然还是在面试中涉及了对本文标题的相关问题-互斥锁和自旋锁的区别.听到这个问题的时候,我是比较忐忑的.互斥锁我还能简单说一些,但是对于自旋锁的了解几乎为零.为此,将总结Linux ...

  2. c#面试题及答案

    1:a=10,b=15,在不用第三方变量的前提下,把a,b的值互换2:已知数组int[] max={6,5,2,9,7,4,0};用快速排序算法按降序对其进行排列,并返回数组3:请简述面向对象的多态的 ...

  3. Heavily reliance on forensic tools is risky

    We could take advantage of forensic tools to examine and analyze the evidence, but heavily reliance ...

  4. Android IOS WebRTC 音视频开发总结(二三)-- hurtc使用说明

    本文主要介绍如何测试基于浏览器和手机的视频通话程序,转载请说明出处,文章来自博客园RTC.Blacker,更多详见www.blackerteam.com   很多人想测试浏览器(包括浏览器版本和桌面e ...

  5. Solaris网络配置

    /etc/hostname.interface:物理端口,里面包含一个主机名或主机的IP/etc/nodename:计算机名/etc/defaultdomain:主机域名/etc/defaultrou ...

  6. 二十、ValueStack的常用方法

    二十.ValueStack的常用方法 void set(String key,Object value):先获取根栈栈顶的Map,如果不存在,压入一个新的Map public String execu ...

  7. MIPS平台移植apache 2.2.7

    参考文章: http://wenku.baidu.com/view/94e08a20a5e9856a561260e2.html http://httpd.apache.org/docs/2.4/ins ...

  8. xls数据导入sqlite数据库

      protected void btn_ok_Click(object sender, EventArgs e)     {         try         {             st ...

  9. ASP.NET相关技术整理

  10. Silverlight动态设置WCF服务Endpoint

    2013-02-02 05:57 by jv9, 1763 阅读, 3 评论, 收藏, 编辑 去年12月收到一位朋友的邮件,咨询Silverlight使用WCF服务,应用部署后一直无法访问的问题,通过 ...