Interaction between Lua and C ++
In the previous section, we implemented a C ++ encapsulation class, through which we can call functions in Lua. However, this does not meet our needs. We also want to use Lua to call our c ++ method. Based on the examples in/tolua ++-1.0.93/src/tests and the features of C ++, I have summarized an example of tolua. It can't be said to be perfect, but the basic functions can already meet the needs of the project. In this example, you can also have a preliminary understanding of tolua syntax and usage.
This example is just a simple example of interaction between Lua and C ++. To learn more about tolua, refer to the example in/tolua ++-1.0.93/src/tests, those examples are quite classic.
In addition, in view of tolua's strength, there may be some unclear descriptions in this article. I hope you can give me some suggestions and I will improve them. If you have any shortcomings, I hope you can correct them. If you have any questions, I will resolve them as soon as possible.
1 code
Ctolua. H (refer to the previous section)
Ctolua. cpp (refer to the previous section)
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 command
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
The functions of these commands have been explained in "tolua ++ installation". If you do not understand them, go there and learn them first.
3 compile and run
Because of the Development in eclipse, eclipse automatically generates makefile for me, so it will not bother to write makefile here. If you do not like to use eclipse, you can use the following lazy compilation method:
G ++-O test *. cpp-ltolua ++
Running result:
1
2
3
4
5
6
7
8
9
10
01
12
23
34
45
56
67
78
89
910
23.69
3.69
// The following is the result of test1.
Cbase
Cchilda
Cchildb
I'm cbase
I'm cchilda
I'm cchildb
// The following is the result of Test2.
Cbase
Cchilda
Cchildb
I'm cbase
I'm cchilda
I'm cchildb
4. Explanation
This example contains global functions, arrays, inheritance, and polymorphism. It not only supports passing custom objects to Lua, but also supports calling methods of C ++ objects. It basically includes the functions we want to implement. In addition, tolua also supports enumeration, namespaces, and variables. For more information, see examples in/tolua ++-1.0.93/src/tests.
Carray. PKG file. $ In $ # include "carray. H" indicates that the subsequent content is inserted to the CPP file generated by tolua.
Cbase. PKG file. Because we pass the cbase * to the parseparameter method by passing the parameter, use va_arg to convert the pointer to void *, and then pass the pointer to the Lua script through lua_pushlightuserdata. In the Lua script, we cannot directly use the void * pointer to perform operations. Instead, we need to convert the pointer to cbase *, so we added the extern cbase * tobase (void * P); Method to convert void * To cbase *. In this case, in the Lua script, you only need to call the tobase method to convert void * To cbase * And then assign the value to a variable, you can use this variable to operate the method of the object actually pointed to by the cbase *. Here the polymorphism feature is displayed.
If we define the class structure and structure in the PKG file, in the Lua file, the constructor maps to new (), the Destructor maps to delete (). The new object in C ++ will be released by C ++, and the object generated in Lua will be released by Lua.
In the main function, before calling the loadluafile method, we need to call the int tolua _ * _ open (lua_state *) method in the CPP generated by tolua. We add the declaration of all open methods to cluacomm. h.
Tolua. callfilefn ("test1", "% Z", & base, & childa, & childb); the method is to pass the generated class to the Lua script for execution.
Tolua. callfilefn ("Test2", ""); directly calls the Test2 method in the Lua script. This method has no parameters.