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

C++混合編程之idlcpp教程Python篇(6),idlcpppython

編輯:C++入門知識

C++混合編程之idlcpp教程Python篇(6),idlcpppython


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

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

工程PythonTutorial4中加入了四個文件:PythonTutorial4.cpp, Tutorial4.cpp, Tutorial4.i, tutorial4.py。這個做法和以前不太一樣,前幾個工程中用.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);
    meta:
        Point(const Point ref pt);
    };

    class Shape : Reference
    {
        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();
    };

}

 

首先是 

#import "../../paf/src/pafcore/Reference.i"

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

第二行

$$#include <vector>

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

在這裡仍然有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 ptr

typeName *

傳地址

typeName ref

typeName &

傳引用

typeName ptr ptr

typeName **

傳指針的地址

typeName new ptr

typeName **

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

typeName new [] ptr

typeName **

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

typeName ptr ref

typeName *&

傳指針的引用

typeName new ref

typeName *&

傳指針的引用,用於接收函數內部new的對象,或者增加引用計數,外界需要delete或release

typeName new [] ref

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 "./Tutorial4.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();
    };

}

 

在類型 Shape 和Triangle中,idlcpp為其添加了虛函數

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

實現代碼見Tutorial4.ic。

此外class Triangle 中除了

static Triangle* New();

static Triangle* NewArray(unsigned int count);

這兩個由構造函數生成的靜態函數外,還多了

static Triangle* NewARC();

static Triangle* NewArrayARC(unsigned int count);

其間的區別見具體實現代碼,實現代碼在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
{

    inline Point* Point::New()
    {
        return new Point();
    }

    inline Point* Point::New(float a,float b)
    {
        return new Point(a, b);
    }

    inline Point* Point::NewArray(unsigned int count)
    {
        return new_array<Point>(count);
    }

    inline Point* Point::Clone(const Point& pt)
    {
        return new Point(pt);
    }

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

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

    inline Triangle* Triangle::New()
    {
        return new ::pafcore::RefCountObject<Triangle>();
    }

    inline Triangle* Triangle::NewARC()
    {
        return new ::pafcore::AtomicRefCountObject<Triangle>();
    }

    inline Triangle* Triangle::NewArray(unsigned int count)
    {
        return new_array<::pafcore::RefCountObject<Triangle>>(count);
    }

    inline Triangle* Triangle::NewArrayARC(unsigned int count)
    {
        return new_array<::pafcore::AtomicRefCountObject<Triangle>>(count);
    }

}

注意一下下面兩個函數的區別

static Triangle* New();

static Triangle* NewARC();

在::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有具體實現代碼,不可在別的地方再次包含。後面是各個類型的成員函數的實現代碼。

PythonTutorial4.cpp代碼和以前的類似,只是去除了上面四個#include語句。

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

 

import pafpython;
paf = pafpython.paf;

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()._);

 

編譯執行,結果如下圖:

 

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