• tolua总结(三)


    Lua与c++互调

    上一节我们实现了一个c++的封装类,通过该类我们就可以调用lua中的函数。可是这还满足不了我们的需求,我们还想通过lua来调用我们c++的方法。通过研究/tolua++-1.0.93/src/tests下的例子,结合c++的特性,我总结了一个tolua的例子。不能说相当完美,但是基本的功能已经能够满足项目的需求了,而且通过这个例子,也可以使各位对tolua的语法以及用法有一个初步的了解。

    本例只是一个简单的lua与c++互调的示例,如果想要更进一步的学习tolua,可以参考/tolua++-1.0.93/src/tests下的例子,那些例子都是相当的经典。

    另外鉴于tolua的强大,文章中可能有一些描述不清楚的地方,望大家能够给予指出,我再给予完善。如有不足之处还望大家给予指正,如有疑问可在评论中指出,我会尽快给予解决。

    1    代码

    CToLua.h(参照上一节)

    CToLua.cpp(参照上一节)

    CArray.h

    #ifndef CARRAY_H_
    #define CARRAY_H_

    struct Point
    {
    float x;
    float y;
    };

    extern int a[10];
    extern Point p[10];
    #endif


    CArray.cpp

    #include "CArray.h"

    int a[10] = {1,2,3,4,5,6,7,8,9,10};
    Point p[10] = {{0,1},{1,2},{2,3},{3,4},{4,5},{5,6},{6,7},{7,8},{8,9},{9,10}};

     

    CBase.h

    #ifndef CBASE_H_
    #define CBASE_H_

    #include <iostream>
    #include <string>
    using namespace std;

    class CBase
    {
    public:
    CBase();
    virtual ~CBase();
    void dispalyName();
    virtual void Print();
    protected:
    string m_sName;
    };

    extern CBase* toBase(void* p);

    #endif


    CBase.cpp

    #include "CBase.h"

    CBase::CBase()
    {
    m_sName = "CBase";
    }

    CBase::~CBase()
    {
    }

    void CBase::dispalyName()
    {
    cout << m_sName <<endl;
    }

    void CBase::Print()
    {
    cout << "I'm CBase" << endl;
    }

    CBase* toBase(void* p)
    {
    return (CBase*)p;
    }

     

    CChildA.h

    #ifndef CCHILDA_H_
    #define CCHILDA_H_

    #include "CBase.h"

    class CChildA : public CBase
    {
    public:
    CChildA();
    ~CChildA();
    void Print();
    };
    #endif


    CChildA.cpp

    #include "CChildA.h"

    CChildA::CChildA()
    {
    m_sName = "CChildA";
    }

    CChildA::~CChildA()
    {
    }

    void CChildA::Print()
    {
    cout << "I'm CChildA" << endl;
    }


    CChildB.h

    #ifndef CCHILDB_H_
    #define CCHILDB_H_

    #include "CBase.h"

    class CChildB : public CBase
    {
    public:
    CChildB();
    ~CChildB();
    void Print();
    };
    #endif


    CChildB.cpp

    #include "CChildB.h"

    CChildB::CChildB()
    {
    m_sName = "CChildB";
    }

    CChildB::~CChildB()
    {
    }

    void CChildB::Print()
    {
    cout << "I'm CChildB" << endl;
    }


    CLuaComm.h

    #ifndef CLUACOMM_H_
    #define CLUACOMM_H_

    int tolua_array_open (lua_State*);
    int tolua_base_open (lua_State*);
    int tolua_childA_open (lua_State*);
    int tolua_childB_open (lua_State*);

    #endif


    mian.cpp

    #include "CToLua.h"
    #include "CLuaComm.h"
    #include "CBase.h"
    #include "CChildA.h"
    #include "CChildB.h"

    int main()
    {
    CToLua tolua;
    tolua_array_open(tolua.getState());
    tolua.loadLuaFile("/home/tolua/test/array.lua");

    tolua_base_open(tolua.getState());
    tolua_childA_open(tolua.getState());
    tolua_childB_open(tolua.getState());
    tolua.loadLuaFile("/home/tolua/test/test.lua");
    double iValue = tolua.callFileFn("add", "%d%f", 20, 3.69); // 23.69
    cout << iValue << endl;
    iValue = tolua.callFileFn("sub", "%f%i", 23.69,20); // 3.69
    cout << iValue << endl;

    CBase base;
    CChildA childA;
    CChildB childB;
    tolua.callFileFn("test1", "%z%z%z", &base, &childA, &childB);
    tolua.callFileFn("test2","");
    return 0;
    }


    CArray.pkg

    $#include "CArray.h"

    struct Point
    {
    float x;
    float y;
    };

    extern int a[10];
    extern const Point p[10];

     

    CBase.pkg

    $#include "CBase.h"

    class CBase
    {
    public:
    CBase();
    virtual ~CBase();
    void dispalyName();
    virtual void Print();
    };

    extern CBase* toBase(void* p);

     

    CChildA.pkg

    $#include "CChildA.h"

    class CChildA : public CBase
    {
    public:
    CChildA();
    ~CChildA();
    void Print();
    };

     

    CChildB.pkg

    $#include "CChildB.h"

    class CChildB : public CBase
    {
    public:
    CChildB();
    ~CChildB();
    void Print();
    };

     

    array.lua

    for i=0,9 do
    print (a[i])
    end

    for i=0,9 do
    print (p[i].x .. p[i].y)
    end

    test.lua

    function add (x,y)
    return x+y
    end

    function sub (x,y)
    return x-y
    end

    function test1 (base,childA,childB)
    b = toBase(base)
    cA = toBase(childA)
    cB = toBase(childB)
    b:dispalyName()
    cA:dispalyName()
    cB:dispalyName()
    b:Print()
    cA:Print()
    cB:Print()
    return 1
    end

    function test2 ()
    b = CBase:new()
    cA = CChildA:new()
    cB = CChildB:new()
    b:dispalyName()
    cA:dispalyName()
    cB:dispalyName()
    b:Print()
    cA:Print()
    cB:Print()
    b:delete()
    cA:delete()
    cB:delete()
    end

    2    命令

    tolua++ -n array -o LArray.cpp CArray.pkg

    tolua++ -n base -o LBase.cpp CBase.pkg

    tolua++ -n childA -o LChildA.cpp CChildA.pkg

    tolua++ -n childB -o LChildB.cpp CChildB.pkg

    这些命令的作用在《tolua++安装》中已经做了解释,不明白的可以去那里先学习一下。

    3    编译&运行

    因为我用的eclipse进行的开发,eclipse自动为我生成了makefile,所以此处就不费事去写makefile了,如果不喜欢使用eclipse的,可以使用如下这个偷懒的编译方式:

    g++ -o test *.cpp -ltolua++

    运行结果:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    01

    12

    23

    34

    45

    56

    67

    78

    89

    910

    23.69

    3.69

    // 以下为test1的结果

    CBase

    CChildA

    CChildB

    I'm CBase

    I'm CChildA

    I'm CChildB

    // 以下为test2的结果

    CBase

    CChildA

    CChildB

    I'm CBase

    I'm CChildA

    I'm CChildB

    4    解说

    这个例子包含了全局函数、数组、继承、多态。不仅支持c++传自定义的对象到lua中,也支持lua调用c++对象的方法。已经基本包含了我们所想要实现的功能。另外tolua还支持枚举、命名空间、变量等,这些可以参考/tolua++-1.0.93/src/tests下的例子,都很易理解。

    CArray.pkg文件。这里边的$#include "CArray.h"中的$代表其后的内容将原方不动的插入到tolua生成的cpp文件中。

    CBase.pkg文件。因为我们通过传参把CBase*传入到parseParameter方法,又利用va_arg将指针转化为void*,再通过lua_pushlightuserdata将指针传入到lua脚本中。在lua脚本中,我们并不能直接使用这个void*的指针去操作,而需要将该指针再转化为CBase*,所以我们添加了extern CBase* toBase(void* p);方法,用来将void*转化为CBase*。这样我们在lua脚本中只需要先调用toBase方法将void*转化为CBase*然后赋值给一个变量,就可以通过这个变量操作该CBase*实际指向的对象的方法了,这里就体现出多态的特性啦。

    如果我们在pkg文件中,也对类得构造和析构做了定义,那么在lua文件中,构造函数将映射为new(),而析构函数将映射为delete()。C++中new的对象将由c++去释放,而在lua中生成的对象将由lua释放。

    在main函数中,我们在调用loadLuaFile方法前,需要先调用tolua生成的cpp中的int tolua_*_open(lua_State*)方法。我们将所有open方法的声明都添加到CLuaComm.h中。

    tolua.callFileFn("test1", "%z%z%z", &base, &childA, &childB);方法是将我们生成的类传入到lua脚本中执行。

    tolua.callFileFn("test2","");是直接调用lua脚本中的test2方法,该方法没有参数。

  • 相关阅读:
    noip2014Day2解题报告
    浴谷八连测R4
    pythonic-让python代码更高效
    java源码学习(一)String
    湖北省汉十高速公路项目接近尾声,所想所感真的值得写写
    jQuery插件ImageBox的使用
    那位兄弟帮忙写个正则表达式哦!急用阿
    如何在页面调用JS函数的代码
    控件的EnableViewState详细分析
    某人给gridview如此集中数据源,我只用过几个,晕倒!!
  • 原文地址:https://www.cnblogs.com/osyun/p/2334214.html
Copyright © 2020-2023  润新知