程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++混合編程之idlcpp教程Lua篇(7),idlcpplua

C++混合編程之idlcpp教程Lua篇(7),idlcpplua

編輯:C++入門知識

C++混合編程之idlcpp教程Lua篇(7),idlcpplua


上一篇在這 C++混合編程之idlcpp教程Lua篇(6)

第一篇在這 C++混合編程之idlcpp教程(一)

與LuaTutorial4工程相似,工程LuaTutorial5中,同樣加入了四個文件:LuaTutorial5.cpp, Tutorial5.cpp, Tutorial5.i, tutorial5.lua。其中LuaTutorial5.cpp的內容基本和LuaTutorial4.cpp雷同,不再贅述。

首先看一下Tutorial5.i的內容:

 

#import "../../paf/src/pafcore/Reference.i"
$$#include <vector>

namespace tutorial
{
    struct Point
    {
        float x;
        float y;
        Point();
        Point(float a, float b);
    meta:
        Point(const Point ref pt);
    };

    export class Shape : Reference
    {
        export abstract float getArea();
        $$        virtual ~Shape() {}
    };

    class ShapeManager(value_object)
    {
        void addShape(Shape ptr shape);
        float getTotalArea();
        static ShapeManager ptr GetInstance();
        $*
        ~ShapeManager();
    private:
        std::vector<Shape*> m_shapes;
        *$
    };


    class Triangle : Shape
    {
        Point m_vertices[$3];
    meta:
        Triangle();
        $$virtual float getArea();
    };

}

 

與Tutorial4.i相比,大部分內容是一樣的,不同之處在於類型Shape的聲明以及其下的純虛函數getArea;

export class Shape : Reference

export abstract float getArea();

在這兩處聲明的最前面都多了一個關鍵字export。這個關鍵字和C++中的export意義完全不一樣,只是想在C++中找一個現成的關鍵字直接使用而已,其實這個也不太合適,暫時先用著。此處的寫法意味著可以在腳本代碼中寫一個類型,讓它“派生”自Shape,並且能夠“覆蓋”虛函數getArea。當然實際上是通過idlcpp生成的一個派生類配合腳本插件代碼來完成類似的任務。

通過在類型的聲明class 前加上關鍵字export 表示此類型可以被腳本“派生”,在虛函數聲明的關鍵字virtual 或 abstract前加上關鍵字export 表示此虛函數可以被腳本“覆蓋”。

在宿主語言和腳本的混合使用中,一個常見的用法是在宿主語言中根據一定的條件向外發出事件,而用腳本語言來編寫事件處理代碼,例如在WOW中用一個XML文件描述GUI界面,同時注明事件處理函數對應的Lua函數名。idlcpp提供的腳本繼承C++類然後重寫虛函數的功能可以很好的實現類似的需求。

編譯後生成的Tutorial5.h的內容如下:

 

//DO NOT EDIT THIS FILE, it is generated by idlcpp
//http://www.idlcpp.org

#pragma once

#include "./Tutorial5.h"
#include "../../paf/src/pafcore/Reference.h"
namespace tutorial{ class ShapeManager; }
namespace tutorial{ class Triangle; }
#include <vector>

namespace tutorial
{
    struct Point
    {
    public:

        float x;
        float y;
        Point();
        Point(float a,float b);
    public:
        static Point* New();
        static Point* New(float a,float b);
        static Point* NewArray(unsigned int count);
        static Point* Clone(const Point& pt);

    };

    class Shape : public ::pafcore::Reference
    {
    public:
        virtual ::pafcore::Type* getType();

        virtual float getArea() = 0 ;
        virtual ~Shape() {}
    };

    class ShapeManager
    {
    public:

        void addShape(Shape* shape);
        float getTotalArea();
        static ShapeManager* GetInstance();

        ~ShapeManager();
    private:
        std::vector<Shape*> m_shapes;
        
    };


    class Triangle : public Shape
    {
    public:
        virtual ::pafcore::Type* getType();

        Point m_vertices[3];
    public:
        static Triangle* New();
        static Triangle* NewARC();
        static Triangle* NewArray(unsigned int count);
        static Triangle* NewArrayARC(unsigned int count);

virtual float getArea();
    };

}

 

這裡生成的代碼和Tutorial4.h基本一致。

最後看一下Tutorial5.lua的內容

 

Circle = {}
Circle.__index = Circle;

function Circle.New()
    circle= {radius = 1.0}
    setmetatable(circle, Circle);
    circle.shape = paf.tutorial.Shape._Derive_(circle);
    return circle;
end

function Circle:getArea()
    return self.radius * self.radius * 3.1415926;
end

circle = Circle.New();
circle.radius = 2.0;
shapeManager = paf.tutorial.ShapeManager.GetInstance();
shapeManager:addShape(circle.shape);
print(shapeManager:getTotalArea()._);

triangle = paf.tutorial.Triangle();
triangle.m_vertices[0] = paf.tutorial.Point(0,0);
triangle.m_vertices[1] = paf.tutorial.Point(0,1);
triangle.m_vertices[2] = paf.tutorial.Point(1,1);
shapeManager:addShape(triangle);
print(shapeManager:getTotalArea()._);

 

在上面的代碼中,寫了一個類型Circle。在函數Circle.New 通過下面這一行

circle.shape = paf.tutorial.Shape._Derive_(circle);

來模擬繼承,語法:C++類型._Derive_(腳本對象) 用於完成模擬繼承的行為。實際上circle.shape才是C++類型Shape的派生類實例的引用,在C++中需要用到Shape類型的地方,將circle.shape傳遞過去即可,如下面的使用方式。

shapeManager:addShape(circle.shape);

然後在類型Circle中提供一個與C++基類同名的函數getArea用來計數圓的面積即可,最終使用時腳本插件會找到對應函數進行調用。

編譯執行,結果如下圖:

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved