用SWIG實現C++和Lua互相調用實例

苦於一直在網上找不到關於C++和Lua互相調用的實例代碼自己寫了一份,比較亂以後有時間整理下。
主要涉及到
c++調用Lua函數。傳遞C++自定義類型
C++調用Lua函數,返回值是自定義類型
Lua函數根據傳進來的自定義C++數據類型進行進行類成員操作。
打算有時間在做Lua返回New出來的C++自定義類型對象,實現內存回收方面的問題。
主要用到SWIG對C++自定義類型進行包裝,方便Lua函數調用。

Lua.i文件,在vs裏面右鍵屬性頁——》自定義生成步驟——》命令行輸入swig -c++ -lua Lua_I.i 編譯就可以自定生成後綴是CXX的文件

頭文件class.h

#pragma once


class  MyClass
{
public:
    void    SetValueA(int iVlue);
    void    SetValueB(float fValue);

    int     GetValueInt(){ return m_iValueA; };
    float   GetVlaueFloat(){ return m_fValueB; };
protected:
    
private:
    int     m_iValueA;
    float   m_fValueB;
};

源文件class.cpp

#include "stdafx.h"
#include "class.h"


void MyClass::SetValueA(int iVlue)
{
    m_iValueA = iVlue;
}

void MyClass::SetValueB(float fVlue)
{
    m_fValueB = fVlue;
}


swig生成腳本lua_i.i
%module Lua_Interface
%{
    #include "Gobal.h"
	#include "class.h"
	#include "MainClass.h"
	
	#define  DEF_LuaPush(type)									\
	void LuaPush(lua_State *L, type *Ptr)						\
	{															\
		SWIG_NewPointerObj(L, Ptr, SWIGTYPE_p_##type, 0);		\
	}

	DEF_LuaPush(MyClass)
	DEF_LuaPush(ComputeClass)
	
	#define DEF_LuaToUserData(type)                             \
	void LuaToUserData(lua_State *L, int index, type **Ptr)		\
	{															\
		SWIG_Lua_ConvertPtr(L, index, (void**)Ptr, SWIGTYPE_p_##type, 0);\
	}
	
	DEF_LuaToUserData(MyClass)
	DEF_LuaToUserData(ComputeClass)
%}

class  MyClass
{
public:
    void    SetValueA(int iVlue);
    void    SetValueB(float fValue);

    int     GetValueInt(){ return m_iValueA; };
    float   GetVlaueFloat(){ return m_fValueB; };
};

class ComputeClass
{
public:
    int ComputeAdd(MyClass& MyClassA, MyClass& MyClassB);
    void ShowResult(int iValue);
    MyClass*    GetMyClassPtr();
};
測試類文件testclass.h
#pragma once
#include "class.h"
//class MyClass;

class ComputeClass
{
public:
    ComputeClass();
    int         ComputeAdd(MyClass& MyClassA, MyClass& MyClassB);
    void        ShowResult(int iValue);
    MyClass*    GetMyClassPtr(){ return &m_MyClass; };
    MyClass     m_MyClass;
};
 

測試類文件testclass.cpp
#include "stdafx.h"
#include "MainClass.h"
#include "class.h"
#include <iostream>

using namespace std;

ComputeClass::ComputeClass()
{
    m_MyClass.SetValueA(10101);
    m_MyClass.SetValueB(20202.02);
}

int ComputeClass::ComputeAdd(MyClass& MyClassA, MyClass& MyClassB)
{
    return MyClassA.GetValueInt() + MyClassB.GetValueInt();
}

void ComputeClass::ShowResult(int iValue)
{
    cout<<"輸出結果值:"<<iValue<<endl;
}
main.cpp
// LuaTest.cpp : 定義控制檯應用程序的入口點。
//

#include<stdio.h>
#include<iostream>

using namespace std;
#include "I_LuaScript.h"
#include "Gobal.h"
#include "class.h"
#include "MainClass.h"

#ifdef __cplusplus
extern "C" {
#endif
    int luaopen_Lua_Interface(lua_State* L);
#ifdef __cplusplus
}
#endif

#include "stdafx.h"
#include "../lua/luaScript.h"


#include "LuaPush.h"

int _tmain(int argc, _TCHAR* argv[])
{
    char Incchar;
    int IncInt = 2;
    CLuaScript::CreateNew();
    //swig初始化
    luaopen_Lua_Interface(LuaScript()->GetHandle());

    LuaScript()->LoadFile("ScriptTest.lua");

    MyClass my1;
    MyClass my2;
    ComputeClass* pCompute = NULL;
    MyClass* pMyClass = NULL;

    my1.SetValueA(666);
    my1.SetValueB(33.22);


    my2.SetValueA(888);
    my2.SetValueB(22.22);

    ComputeClass cmp;
    cmp.m_MyClass.SetValueA(7878);
    cmp.m_MyClass.SetValueB(66.88);

    //system("PAUSE");

    while (cin>>IncInt && IncInt!= 0)
    {
        if (IncInt == 1)
        {
            if(LuaScript()->HasLuaFunc("ComputeValue"))	
            {
                CallLuaFunc("ComputeValue",&my1, &my2, &cmp);
            }
        }
        else if (IncInt == 2)
        {
            if(LuaScript()->HasLuaFunc("TestPrintd"))	
            {
                CallLuaFunc("TestPrintd",&my1, &my2, &cmp);
            }
        }
        else if (IncInt == 888)
        {
            LuaScript()->LoadFile("ScriptTest.lua");
        }
        else if (IncInt == 3)
        {
            if(LuaScript()->HasLuaFunc("ComputePrintd"))	
            {
                CallLuaFunc("ComputePrintd",&my1, &my2, &cmp);
            }
        }
        else if (IncInt == 4)
        {
            if(LuaScript()->HasLuaFunc("TestPrintdValue"))	
            {
                CallLuaFunc("TestPrintdValue",IncInt);
            }
        }
        else if (IncInt == 5)
        {
            if(LuaScript()->HasLuaFunc("TestGetPtr"))	
            {
                CallLuaFunc("TestGetPtr",&cmp);
            }
        }
        else if (IncInt == 6)
        {
            if(LuaScript()->HasLuaFunc("TestReturnPtr"))	
            {
                CallScriptFunc_1I_Ret1I("TestReturnPtr",&cmp, &pCompute);
                if (pCompute != NULL)
                {
                    cout<<"Lua函數返回指針對象輸出GetValueInt():"<<pCompute->GetMyClassPtr()->GetValueInt()<<endl;
                }
            }
        }
        else if (IncInt == 7)
        {
            if(LuaScript()->HasLuaFunc("TestReturnProcessPtr"))	
            {
                CallScriptFunc_1I_Ret1I("TestReturnProcessPtr",&my1, &pMyClass);
                if (pMyClass != NULL)
                {
                    cout<<"Lua函數返回修改過的指針對象輸出GetValueInt():"<<pMyClass->GetValueInt()<<endl;
                }
            }
        }
    }

   
    CLuaScript::ReleaseLuaScript();

	return 0;
}

根據生成的CXX文件函數生命Luapush.h
#pragma once

#include "I_LuaScript.h"

#define  PROTO_LuaPush(type)		class type; void LuaPush(lua_State *L, type *Ptr);
PROTO_LuaPush(MyClass)
PROTO_LuaPush(ComputeClass)


#define  PROTO_LuaToUserData(type)		class type; void LuaToUserData(lua_State *L, int index, type **Ptr);
PROTO_LuaToUserData(MyClass)
PROTO_LuaToUserData(ComputeClass)


未完待續




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章