zoukankan      html  css  js  c++  java
  • C++混合编程之idlcpp教程Python篇(6)

    上一篇在这 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);
            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 编译时先将其所描述的文件中的内容插入到对应的位置。

    第二行

    ###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 *

    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的内容

    //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有具体实现代码,不可在别的地方再次包含。后面是各个类型的成员函数的实现代码。

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

    编译执行,结果如下图:

  • 相关阅读:
    Asp.net 中 OnClientClick 与 OnClick 的区别
    WPF + RDLC + Tablix动态生成列 + 表头合并
    统计表用于查询效果太差的情况
    TeamView WaitforConnectFailed错误原因
    瞄到BindingGroup用法
    最讨厌工作时候百度的信息
    Lambda获取类属性的名字
    附加属性作用于多选控件,用于获取所有选中项
    文件夹图标错落解决方案
    WPF Line 的颜色过度动画
  • 原文地址:https://www.cnblogs.com/fdyjfd/p/5388939.html
Copyright © 2011-2022 走看看