IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> lua学习03:tolua的编译和使用:C/C++调用lua、lua调用C++、lua调用tolua -> 正文阅读

[游戏开发]lua学习03:tolua的编译和使用:C/C++调用lua、lua调用C++、lua调用tolua

一、编译及使用流程

1)编译lua静态库

必须先下载lua 1.5,下载好后,把/src目录的除开lua.c,luac.c的文件全部放到一个新建的静态链接库的工程项目里,然后编译出一个静态链接库lua.lib。

2)编译tolua++静态库

去tolua++官网下载一个tolua++的包,解压出来,再次新建一个静态链接库的项目,把tolua++的/src/lib里的.h .c的文件拷贝到静态链接库的项目里,然后编译出一个tolua++.lib 的库。

3)编译tolua++.exe

再次新建一个控制台程序的项目,把编译好的lua静态库和tolua++的静态库放在项目里附加,然后把tolua++的/src/bin/里的tolua.c,luabind.h,luabind.c文件放在项目里,然后把tolua++的/include里的tolua++.h和lua1.5的目录里的/src的所有头文件放到项目里,然后编译生成tolua++.exe

4)根据C/C++文件编写好对应的pkg文件,然后根据一创命令生成tolua

(1)C文件举例

  • C文件(test1.c)
#define FALSE 0
#define TRUE 1

enum { 
 POINT = 100, 
 LINE, 
 POLYGON
}
Object* createObejct (int type);
void drawObject (Object* obj, double red, double green, double blue);
int isSelected (Object* obj);

就会自动创建一个绑定上面代码到lua的C文件。因此,在lua代码里, 我们可以访问C代码。举个例子:

  • pkg文件
$pfile "XX.pkg"    //$pfile是包含对应的pkg文件
$hfile  "XXX.h"     //$hfile是包含对应的.h头文件
$lfile  "XXX.lua"    //包含对应的.lua文件
  • 生成命令 (tolua -h显示当前可接受的选项)
    1)要解析一个名为test.pkg生成一个名为tolua_test.c的绑定代码,我们需要输入:
    tolua -o test.c test.pkg
    2)或生成一个不同的名字给pkg
    tolua -n pkgname -o myfile.c myfile.pkg

  • 调用流程展示

...
myLine = createObject(LINE)				--
...
if isSelected(myLine) == TRUE then
  drawObject(myLine, 1.0, 0.0, 0.0);
else
  drawObject(myLine, 1.0, 1.0, 1.0);
end
...

(2)C++文件举例

  • C++文件
#define FALSE 0
#define TRUE 1
class Shape
{
  void draw (void);
  void draw (double red, double green, double blue);
  int isSelected (void);
};
class Line : public Shape
{
 Line (double x1, double y1, double x2, double y2);
 ~Line (void);
};

如果tolua输入加载该文件,就会自动生成一个C++文件,例如tolua,从而为我们提供lua层访问C++层所需要的对应的代码。因此,以下的的lua代码是有效的:

...
myLine = Line:new (0,0,1,1)				--new表示创建一个类的新对象,这个对象是myLine
...
if myLine:isSelected() == TRUE then		--对象::对应函数表示调用对应函数
 myLine:draw(1.0,0.0,0.0)
else
 myLine:draw()							--基类的函数也是直接调用就行
end
...
myLine:delete()							--delete就是析构函数
...

二、C++调用lua

1)流程

(1)package还应当被明确初始化。为了从C/C++代码中初始化package,我们需要声明和调用初始化函数。初始化函数被定义为:

int tolua_pkgname_open (lua_State*); //这就是C++的函数,pkgname填写对应pkg的名字

(2)如果我们使用的是C++,我们可以选择自动初始化

tolua -a -n pkgname -o myfile.c myfile.pkg
不使用自动初始化是(下面的命令):
tolua -n pkgname -o tolua_myfile.c myfile.pkg //生成tolua_myfile.c文件

2)注意点:

在这种情况下,初始化函数会被自动调用。然而,如果我们计划使用多个Lua State,自动初始化就行不通了,因为静态变量初始化的顺序在C++里没有定义。

  • 补充
    tolua生成的绑定代码使用了一系列tolua库里面的函数。因此,这个库同样需要被链接到应用程序中。tolua.h也是有必须要编译生成的代码。tolua生成的绑定代码使用了一系列tolua库里面的函数。因此,这个库同样需要被链接到应用程序中。tolua.h也是有必须要编译生成的代码。

3)要包含的库和头文件

库: lua.lib 和 tolua.lib
头文件:lua.h、lualib.h、lauxlib.h、luaconf.h

4)代码示例

//main.cpp
#include <iostream>
extern "C"
{
#include "lualib.h"
#include "lauxlib.h"
}

using namespace std;

int main()
{
    int tolua_mylib_open(lua_State*);
    lua_State* state = luaL_newstate();
    luaL_openlibs(state);

    if (luaL_dostring(state, "print([[hello world]])") != 0)
    {
        cout << "excute lua file failed!" << endl;
    }
    lua_close(state);

    system("pause");
    return 0;
}

如果正确打印出 “hello world”,则说明 lua 环境没有问题,否则就检查一下头文件和库文件是否正确引入了

5)生成函数的API介绍

  • 原始.c和.h文件
//.h文件
//mylib.h
class Test
{
public:
    Test(int a, int b);
    ~Test();
    void sayHello();
    int add();
    int getA();

private:
    int a;
    int b;
};


//.cpp文件
//mylib.cpp
#include "mylib.h"
#include <iostream>

Test::Test(int a, int b)
{
    this->a = a;
    this->b = b;
}

Test::~Test()
{
}

void Test::sayHello()
{
    std::cout << "hello world" << std::endl;
}

int Test::add()
{
    return this->a + this->b;
}

int Test::getA()
{
    return this->a;
}

编译指令:tolua -n mylib -o tolua.cpp mylib.pkg

  • pkg文件
$#include "mylib.h"
class Test
{
    Test(int, int);
    ~Test();
    void sayHello();
    int add();  
    int getA();
};
  • 生成代码
//类名是Test

//垃圾回收
static int tolua_collect_Test (lua_State* tolua_S){}    

//注册类名
static void tolua_reg_types (lua_State* tolua_S){}

//对应构造函数
static int tolua_mylib_Test_new00(lua_State* tolua_S){}

//对应析构函数
static int tolua_mylib_Test_delete00(lua_State* tolua_S){}

//对应sayHello函数
static int tolua_mylib_Test_sayHello00(lua_State* tolua_S){}

//对应add函数
static int tolua_mylib_Test_add00(lua_State* tolua_S){}

//getA
static int tolua_mylib_Test_getA00(lua_State* tolua_S){}

//luaopen_pkgname用于打开库文件
LUALIB_API int luaopen_mylib (lua_State* tolua_S){}

//luaopen_pkgname_open于打开 tolua,然后lua就可以使用C++的函数了
TOLUA_API int tolua_mylib_open (lua_State* tolua_S){}

三、lua调用C++

1)代码

  • lua文件
local test = Test:new(1, 2)
test:sayHello()
print("a = " .. test:getA())
print("a + b = " .. test:add())
  • cpp文件
#include <iostream>
extern "C"
{
#include "lualib.h"
#include "lauxlib.h"
}
//Test类的源文件mylib.h
#include "mylib.h"

using namespace std;

int main()
{
    lua_State* state = luaL_newstate();	//创建lua虚拟机
    luaL_openlibs(state);				//打开lua的库
    tolua_mylib_open(state);			//打开tolua的入口,让lua可以调用mylib的C++类接口


    if (luaL_dofile(state, "scripts/test.lua") != 0)//加载test.lua文件
    {
        cout << "excute lua file failed!" << endl;
        lua_close(state);
        return 1;
    }
    lua_close(state);

    system("pause");
    return 0;
}

2)执行结果

在这里插入图片描述

四、lua调用tolua

这种方式其实和在 c++ 程序中使用 tolua 没什么区别,只是我们测试的项目是 c++ 项目还是 lua 项目而已。要在纯 lua 程序中使用 tolua,首先得导出一个 c++ 模块。新建一个 c++ 动态链接库项目,同样地将 lua 和 tolua 的头文件和库文件包含进来,还有 mylib.h、mylib.cpp 和 tolua.cpp 这三个文件也添加进项目来。

导出 c++ 模块,在模块内注册一个函数,在这个函数里打开 tolua,然后 tolua 绑定的所有 c++ 函数就可以在 lua 中使用了。我们创建一个 lib.h 和 lib.cpp 文件,用于导出 c++ 模块

  • .h文件
//lib.h
#pragma once
#include "lua.h"
extern "C"
{
    __declspec(dllexport) int luaopen_test(lua_State* L);
}
  • .cpp文件
//lib.cpp
#include "mylib.h"
extern "C"
{
#include "lib.h"
#include "lualib.h"
#include "lauxlib.h"
}

static int export_tolua_test(lua_State* L)
{
    int tolua_mylib_open(lua_State* L);
    tolua_mylib_open(L);
    return 1;
}
static const luaL_Reg toluaTest[] =
{
    { "export_tolua_test",export_tolua_test },
    { NULL,NULL }
};

extern "C"
{
    __declspec(dllexport) int luaopen_test(lua_State* L)
    {
        luaL_newlibtable(L, toluaTest);
        luaL_setfuncs(L, toluaTest, 0);
        return 1;
    }
}

编译之后得到一个 lib.dll 文件,在 lua 代码中加载这个动态链接库文件,得到一个模块,这个模块里面有 export_tolua_test 这个函数,调用这个函数就会执行 tolua_mylib_open(L);,从而打开 tolua,则在 mylib 中导出的所有 c++ 东西都可以在 lua 中使用了

-- main.lua
-- 加载 c++ 模块
local test = require("test")
-- 调用 c++ 模块注册的函数,这个函数会打开 tolua
test.export_tolua_test()

-- 调用 tolua 导出的类、函数等
local t = Test:new(10, 20)
t:sayHello()
print(t:getA())
print(t:add())

使用 lua 解释器运行该代码,看到下面的执行结果

在这里插入图片描述

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2021-12-13 13:11:29  更:2021-12-13 13:13:09 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 20:33:42-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码