C++混合編程之idlcpp教程Lua篇(6)

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

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

工程LuaTutorial4中加入了四個文件:LuaTutorial4.cpp, Tutorial4.cpp, Tutorial4.i, tutorial4.lua。這個作法和之前不太同樣,前幾個工程中用.i文件生成的頭文件時,類型的成員函數都是用內聯的方式寫在頭文件中。實際上按C++的使用習慣來講只有簡短的函數建議之內聯方式實現,其他的函數通常寫在另外一個對應的.cpp文件中。此處加入的Tutorial4.cpp就是這個用法。編程

首先看一下Tutorial4.i的內容:數組

 

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

namespace tutorial
{
    struct Point
    {
        float x;
        float y;
        Point();
        Point(float a, float b);
        nocode Point(const Point& pt);
    };

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

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


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

}

 

 

首先是 多線程

#import "../../paf/src/pafcore/Reference.i"編程語言

#import至關於C++中的 #include 編譯時先將其所描述的文件中的內容插入到對應的位置。函數

第二行 post

###include <vector>this

將#include <vector> 插入到Tutorial4.h的對應位置上。lua

在這裏仍然有struct Point,但因爲其中構造函數的實現代碼將會放到Tutorial4.cpp中。因此寫法和之前有所不一樣。

而後是

class Shape : Reference

對照一下上一節的寫法 struct Shape 有兩處不一樣,一是使用了關鍵字class 替代了struct 二是使用了基類Reference。這個基類是運行時庫pafcore提供的,具體內容請參看 Reference.i。class Reference 位於 namespace pafcore下。

許多編程語言對於內存管理都提供了內置的支持,C#,Java,Lua,Python等都有垃圾收集機制,然而在C++中沒有這種機制,通常須要程序員手工維護對象的生命期。一種經常使用的方法是引用計數,引用計數算是一種簡潔高效的手段了。在idlcpp中提供了引用計數的直接支持。類 ::pafcore::Reference 提供了用於引用計數的基本接口。而關鍵字class 默認其描述的類型直接或間接派生自::pafcore::Reference,使用struct 則沒有這個假設,注意此處和C++不一樣。另外若是在idlcpp中使用struct ,則在生成的C++類型中也使用struct 作關鍵字;若是在idlcpp中使用class ,則在生成的C++類型中也使用class 作關鍵字。若是想在C++中使用關鍵字class 且又不想讓其派生自::pafcore::Reference,idlcpp提供了相應的語法來處理這種狀況,見下表:

 

idlcpp

C++

struct A

struct A

class A

class A : public ::pafcore::Reference

struct A(reference_object)

struct A : public ::pafcore::Reference

class A(value_object)

class A

 

 

而後是

class ShapeManager(value_object)

如前所述,但願在C++中使用class關鍵字而又不須要派生自::pafcore::Reference,在類型的名字後面加上(value_object)便可。

 

在class ShapeManager提供了三個接口函數。第一個函數void addShape(Shape ptr shape);在其參數中出現了關鍵字ptr。這個至關於C++中的*,表示傳指針,之因此不使用*而使用ptr代替的緣由見上一節。idlcpp在函數聲明的參數傳遞類型部分有以下幾種形式:

 

 

idlcpp聲明

C++聲明

實現

typeName

typeName

輸入參數,傳值

typeName *

typeName *

輸入參數,傳地址

typeName &

typeName &

輸入參數,傳引用

typeName **

typeName **

輸出參數,傳指針的地址,用於接收要返回的指針

typeName ^*

typeName **

輸出參數,傳指針的地址,用於接收函數內部new的對象,或者增長引用計數,外界須要delete或release

typeName ^[] *

typeName **

輸出參數,傳指針的地址,用於接收函數內部new []的對象數組,外界須要delete []

typeName *&

typeName *&

輸出參數,傳指針的引用,用於接收要返回的指針

typeName ^&

typeName *&

輸出參數,傳指針的引用,用於接收函數內部new的對象,或者增長引用計數,外界須要delete或release

typeName ^[] &

typeName *&

輸出參數,傳指針的引用,用於接收函數內部new []的對象數組,外界須要delete []

 

 

 

最後的

class Triangle : Shape

 和上一節同樣,只不過Shape派生自::pafcore::Reference;所以class Triangle 也有引用計數的功能。

編譯後生成的Tutorial4.h的內容以下:

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

#pragma once

#include "../../paf/src/pafcore/Typedef.h"
#include "../../paf/src/pafcore/Reference.h"
#include <vector>

namespace tutorial
{
    struct Point
    {
    public:

        float x;
        float y;
        Point();
        Point(float a,float b);
    };

    class Shape : public pafcore::Reference
    {
    public:
        static ::pafcore::ClassType* GetType();
        virtual ::pafcore::ClassType* getType();
        virtual size_t getAddress();

        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:
        static ::pafcore::ClassType* GetType();
        virtual ::pafcore::ClassType* getType();
        virtual size_t getAddress();

        Point m_vertices[3];
        virtual float getArea();
    };

}

 

在類型 Shape 和Triangle中,idlcpp爲其添加了靜態函數

static ::pafcore::ClassType* GetType();

和兩個虛函數

virtual ::pafcore::Type* getType();

virtual size_t getAddress();

Reference 的派生類會自動生成這兩個虛函數,實現代碼見Tutorial4.ic。

下面是Tutorial4.ic的內容

其間的區別見具體實現代碼,實現代碼在Tutorial4.ic中。

下面是Tutorial4.ic的內容

  

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

#pragma once

#include "Tutorial4.h"
#include "Tutorial4.mh"
#include "../../paf/src/pafcore/RefCount.h"

namespace tutorial
{

    ::pafcore::ClassType* Shape::GetType()
    {
        return ::RuntimeTypeOf<Shape>::RuntimeType::GetSingleton();
    }

    ::pafcore::ClassType* Shape::getType()
    {
        return ::RuntimeTypeOf<Shape>::RuntimeType::GetSingleton();
    }

    size_t Shape::getAddress()
    {
        return (size_t)this;
    }

    ::pafcore::ClassType* Triangle::GetType()
    {
        return ::RuntimeTypeOf<Triangle>::RuntimeType::GetSingleton();
    }

    ::pafcore::ClassType* Triangle::getType()
    {
        return ::RuntimeTypeOf<Triangle>::RuntimeType::GetSingleton();
    }

    size_t Triangle::getAddress()
    {
        return (size_t)this;
    }

}

 

在元數據文件中對應的 Triangle 類型除了實現New()函數外,還有NewARC()函數,一樣也返回一個 new 的 Triangle 指針,二者不一樣之處以下所述。

在::pafcore::Reference中僅僅提供了引用計數的接口,引用計數的具體實現方法是多種多樣的,pafcore中提供的一種實現方法。具體參見pafcore中的文件RefCount.h。其中提供了兩個模板類RefCountObject和AtomicRefCountObject。其中AtomicRefCountObject用原子操做處理引用計數,可用於多線程同時訪問對象引用計數的狀況。在idlcpp生成的New函數和NewARC函數中分別使用了這兩個模板類,用戶能夠根據具體狀況調用不一樣的函數。

再看一下Tutorial4.cpp的內容

 

#include "Tutorial4.h"
#include "Tutorial4.mh"
#include "Tutorial4.ic"
#include "Tutorial4.mc"


namespace tutorial
{

    Point::Point()
    {}

    Point::Point(float a, float b)
    {
        x = a;
        y = b;
    }
    
    ShapeManager* ShapeManager::GetInstance()
    {
        static ShapeManager s_instance;
        return &s_instance;
    }
    ShapeManager::~ShapeManager()
    {
        auto it = m_shapes.begin();
        auto end = m_shapes.end();
        for (; it != end; ++it)
        {
            Shape* shape = (*it);
            shape->release();
        }
    }
    void ShapeManager::addShape(Shape* shape)
    {
        shape->addRef();
        m_shapes.push_back(shape);
    }

    float ShapeManager::getTotalArea()
    {
        float area = 0;
        auto it = m_shapes.begin();
        auto end = m_shapes.end();
        for (; it != end; ++it)
        {
            Shape* shape = (*it);
            area += shape->getArea();
        }
        return area;
    }
    

    float Triangle::getArea()
    {
        return fabs(m_vertices[0].x * m_vertices[1].y + m_vertices[1].x * m_vertices[2].y + m_vertices[2].x * m_vertices[0].y
            - m_vertices[0].x * m_vertices[2].y - m_vertices[1].x * m_vertices[0].y - m_vertices[2].x * m_vertices[1].y) * 0.5;
    }

}

 

最上面四行將idlcpp生成的四個代碼文件包含進來,其中Tutorial4.ic和Tutorial4.mc有具體實現代碼,不可在別的地方再次包含。後面是各個類型的成員函數的實現代碼。

LuaTutorial4.cpp代碼和之前的相似,只是去除了上面四個#include語句。

最後看一下腳本tutorial4.lua的內容:

 

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 = paf.tutorial.ShapeManager.GetInstance(); shapeManager:addShape(triangle); print(shapeManager:getTotalArea()._);

 

編譯執行,結果以下圖:

相關文章
相關標籤/搜索