上一篇在这 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[#];
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() = ;
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[];
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 = ;
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[].x * m_vertices[].y + m_vertices[].x * m_vertices[].y + m_vertices[].x * m_vertices[].y
- m_vertices[].x * m_vertices[].y - m_vertices[].x * m_vertices[].y - m_vertices[].x * m_vertices[].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()._);

编译执行,结果如下图:

C++混合编程之idlcpp教程Python篇(6)的更多相关文章

  1. C++混合编程之idlcpp教程Python篇(9)

    上一篇在这 C++混合编程之idlcpp教程Python篇(8) 第一篇在这 C++混合编程之idlcpp教程(一) 与前面的工程相比,工程PythonTutorial7中除了四个文件PythonTu ...

  2. C++混合编程之idlcpp教程Python篇(8)

    上一篇在这 C++混合编程之idlcpp教程Python篇(7) 第一篇在这 C++混合编程之idlcpp教程(一) 与前面的工程相似,工程PythonTutorial6中,同样加入了四个文件:Pyt ...

  3. C++混合编程之idlcpp教程Python篇(7)

    上一篇在这 C++混合编程之idlcpp教程Python篇(6) 第一篇在这 C++混合编程之idlcpp教程(一) 与PythonTutorial4工程相似,工程PythonTutorial5中,同 ...

  4. C++混合编程之idlcpp教程Python篇(5)

    上一篇在这  C++混合编程之idlcpp教程Python篇(4) 第一篇在这 C++混合编程之idlcpp教程(一) 与前面的工程相似,工程PythonTutorial3中,同样加入了三个文件:Py ...

  5. C++混合编程之idlcpp教程Python篇(4)

    上一篇在这 C++混合编程之idlcpp教程Python篇(3) 第一篇在这 C++混合编程之idlcpp教程(一) 与前面的工程相似,工程PythonTutorial2中,同样加入了三个文件 Pyt ...

  6. C++混合编程之idlcpp教程Python篇(3)

    上一篇 C++混合编程之idlcpp教程Python篇(2) 是一个 hello world 的例子,仅仅涉及了静态函数的调用.这一篇会有新的内容. 与PythonTutorial0相似,工程Pyth ...

  7. C++混合编程之idlcpp教程Python篇(2)

    在上一篇 C++混合编程之idlcpp教程(一) 中介绍了 idlcpp 工具的使用.现在对 idlcpp 所带的示例教程进行讲解,这里针对的 Python 语言的例子.首先看第一个示例程序 Pyth ...

  8. C++混合编程之idlcpp教程Lua篇(6)

    上一篇在这 C++混合编程之idlcpp教程Lua篇(5) 第一篇在这 C++混合编程之idlcpp教程(一) 工程LuaTutorial4中加入了四个文件:LuaTutorial4.cpp, Tut ...

  9. C++混合编程之idlcpp教程Lua篇(9)

    上一篇在这 C++混合编程之idlcpp教程Lua篇(8) 第一篇在这 C++混合编程之idlcpp教程(一) 与前面的工程相比,工程LuaTutorial7中除了四个文件LuaTutorial7.c ...

随机推荐

  1. 记录Qt的一个诡异Bug

    公司的一款项目,在迭代开发阶段,突然发现运行速度越来越慢,界面切换卡顿时间在2秒以上.经过和某个不卡版本的对比,惊奇的发现程序二进制都一模一样,就几个图片资源和脚本不一样.经过差不多一天的排查,发现是 ...

  2. 对于cookie和session的形象解释

    生活中的场景: 一群人,买豆浆,也不排队,乱哄哄的 豆浆现磨. 先交钱,交完钱蹲在一边等. 这个老板非常健忘! 记忆时间:转脸就忘. 李四给老板钱<--->"大杯黄豆!" ...

  3. [PHP] Xhprof 非侵入式使用指南

    一般使用 Xhprof ,按文档操作可以快速上手,文件头开启 Xhprof,应用结束处得到访问的url查看. 这种使用方式可以快速看到效果,同时也有一些不好的地方: 一是不利于重复利用写好的示例代码: ...

  4. BOOTSTRAP定制

    1.补充:栅格系统中调整列的位置/顺序 (1)方法1:偏移量(col-*-offset-*) (2)方法2:对列进行push/pull操作 col-lg-pull-1        ~         ...

  5. ArrayList与LinkedList用法与区别

    1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构.  2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedLis ...

  6. 在rails 4 中 使用 CSV 组件来 把csv文件导入到数据库

    class HardWorker include Sidekiq::Worker require 'CSV' def perform(file_path) csv_text = File.read(f ...

  7. 18.safari 安装后flash还是提示安装 flash,视频不能播放

    第一步: safari---->偏好设置(首先安装最新Mac adobe flash) 第二步: 第三步:点击进入 第四步:再次打开safar,大功告成!

  8. Linux 将文件夹下的所有文件复制到另一个文件里

    如何将文件夹/home/work下的文件复制到/home/temp里面? 使用命令: cp -R /home/work/* /home/temp *表示所有文件 但是/home/work 下的隐藏文件 ...

  9. oracle方案是什么?

    某用户拥有的所有的数据库对象的逻辑集合,就叫方案:方案在名称上和用户名是相同的. 比如有一个Oracle"用户"叫scott,那么一般称Scott用户所拥有的所有数据库对象的集合叫 ...

  10. CSS 自定义字体

    移动端如何兼容UI给的字体 [toc] 移动端的默认字体 IOS 默认中文字体是Heiti SC 默认英文字体是Helvetica 默认数字字体是HelveticaNeue Android 默认中文字 ...