上一篇在這 C++混合編程之idlcpp教程Python篇(3)
第一篇在這 C++混合編程之idlcpp教程(一)
與前面的工程相似,工程PythonTutorial2中,同樣加入了三個文件 PythonTutorial2.cpp, Tutorial2.i, tutorial2.py。其中PythonTutorial2.cpp的內容基本和PythonTutorial1.cpp雷同,不再贅述。首先看一下Tutorial2.i的內容:
namespace tutorial { struct Point { float x; float y; meta: Point(); Point(float a, float b); $* Point() {} Point(float a, float b) { x = a; y = b; } *$ }; struct Rectangle { Point m_min; Point m_max; float left set get; float right set get; meta: float bottom set get; float top set get; float area get; float getArea(); all: Rectangle(const Point ref min, const Point ref max); Rectangle(); meta: Rectangle(const Rectangle ref pt); $* void set_bottom(float bottom) { m_min.y = bottom; } float get_bottom() { return m_min.y; } void set_top(float top) { m_max.y = top; } float get_top() { return m_max.y; } float get_area() { return (m_max.x - m_min.x)*(m_max.y - m_min.y); } float getArea() { return (m_max.x - m_min.x)*(m_max.y - m_min.y); } *$ }; $* inline Rectangle::Rectangle(const Point& min, const Point& max) : m_min(min), m_max(max) { } inline Rectangle::Rectangle() {} inline float Rectangle::get_left() { return m_min.x; } inline void Rectangle::set_left(float left) { m_min.x = left; } inline float Rectangle::get_right() { return m_max.x; } inline void Rectangle::set_right(float right) { m_max.x = right; } *$ }
在這裡仍然有struct Point。與PythonTutorial1中的struct Point相比,除了原來的默認構造函數外,多了一個帶兩個參數的構造函數
Point(float a, float b);
兩個構造函數都在meta: 段中,所以idlcpp不會在Tutorial2.h中生成對應的函數聲明,所在直接在後面的$**$寫上構造函數的實現代碼,這些代碼會插入到Tutorial2.h中的對應位置。當然也可以不使用meta:,這樣的話這兩個構造函數的聲明部分就會出現在Tutorial2.h的struct Point中,那麼實現代碼就要寫在外面了。在struct Point後添加了一個新的類型struct Rectangle。前兩行
Point m_min;
Point m_max;
聲明了兩個數據成員。然後是
float left set get;
float right set get;
這裡又出現了新的語法:屬性。屬性語法來自於C#。形式為: 類型 + 名稱 + 可選的set和get。在C++中實際上是生成了兩個對應的成員函數,函數名分別為set_ + 屬性名稱,get_ + 屬性名稱,比如為屬性left生成的兩個成員函數為:void set_left(float)和float get_left()。然後還有三個屬性的聲明
float bottom set get;
float top set get;
float area get;
其中屬性area是只讀屬性,即只生成float get_area()成員函數。然後是
float getArea();
這是一個成員函數,在C++生成中的函數形式和這裡是一樣的。然後是
Rectangle(const Point ref min, const Point ref max);
這是一個構造函數,這裡出現了一個新的關鍵字ref。關鍵字ref也來自於C#,相當於C++中函數參數聲明中的&。類似的還有一個關鍵字ptr,相當於C++中函數參數聲明中的*。之所以使用ref而不是& 是因為指針的緣故。在C++中指針的用法比較自由,在idlcpp中對指針的使用做了一定的限制,考慮到其中的差異,避免在移植現有C++代碼到idl中出現遺漏,決定采用ptr代替*,為了看起來統一,同樣也用ref取代了&。所以此處對應的C++代碼為
Rectangle(const Point& min,const Point& max);
後面就是具體函數的實現代碼。都放在$**$中以便復制到頭文件中。
編譯後生成的Tutorial2.h的內容如下:
//DO NOT EDIT THIS FILE, it is generated by idlcpp //http://www.idlcpp.org #pragma once #include "./Tutorial2.h" namespace tutorial{ struct Rectangle; } namespace tutorial { struct Point { public: float x; float y; public: static Point* New(); static Point* New(float a,float b); static Point* NewArray(unsigned int count); Point() {} Point(float a, float b) { x = a; y = b; } }; struct Rectangle { public: Point m_min; Point m_max; void set_left( float); float get_left(); void set_right( float); float get_right(); Rectangle(const Point& min,const Point& max); Rectangle(); public: static Rectangle* New(const Point& min,const Point& max); static Rectangle* New(); static Rectangle* NewArray(unsigned int count); static Rectangle* Clone(const Rectangle& pt); void set_bottom(float bottom) { m_min.y = bottom; } float get_bottom() { return m_min.y; } void set_top(float top) { m_max.y = top; } float get_top() { return m_max.y; } float get_area() { return (m_max.x - m_min.x)*(m_max.y - m_min.y); } float getArea() { return (m_max.x - m_min.x)*(m_max.y - m_min.y); } }; inline Rectangle::Rectangle(const Point& min, const Point& max) : m_min(min), m_max(max) { } inline Rectangle::Rectangle() {} inline float Rectangle::get_left() { return m_min.x; } inline void Rectangle::set_left(float left) { m_min.x = left; } inline float Rectangle::get_right() { return m_max.x; } inline void Rectangle::set_right(float right) { m_max.x = right; } }
內容基本上都是和Tutorial2.i中一一對應的,在Point和Rectangle中各有幾個靜態函數,名字如下:New,Clone,NewArray。這些都是根據構造函數的形式生成的。這些函數的實現代碼在Tutorial2.ic中。編譯後生成的Tutorial2.ic的內容如下:
//DO NOT EDIT THIS FILE, it is generated by idlcpp //http://www.idlcpp.org #pragma once #include "Tutorial2.h" #include "Tutorial2.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 Rectangle* Rectangle::New(const Point& min,const Point& max) { return new Rectangle(min, max); } inline Rectangle* Rectangle::New() { return new Rectangle(); } inline Rectangle* Rectangle::NewArray(unsigned int count) { return new_array<Rectangle>(count); } inline Rectangle* Rectangle::Clone(const Rectangle& pt) { return new Rectangle(pt); } }
然後看一下腳本tutorial2.py的內容:
import pafpython; paf = pafpython.paf; rect1 = paf.tutorial.Rectangle(); rect1.m_min.x = 1; rect1.m_min.y = 2; print(rect1.left._); print(rect1.bottom._); rect1.right = 3; rect1.top = 4; print(rect1.m_max.x._); print(rect1.m_max.y._); print(rect1.area._); rect2 = paf.tutorial.Rectangle(rect1.m_min, paf.tutorial.Point(5,5)); print(rect2.getArea()._); rect3 = paf.tutorial.Rectangle.Clone(rect2); print(rect3.getArea()._);
rect1 = paf.tutorial.Rectangle();
這是rect1 = paf.tutorial.Rectangle.New(); 的簡化寫法。
後面分別用數據成員和屬性來操作rect1。
rect2 = paf.tutorial.Rectangle(rect1.m_min, paf.tutorial.Point(5,5));
調用了Rectangle帶參數的構造函數(實際上是靜態函數New)。
rect3 = paf.tutorial.Rectangle.Clone(rect2);
相當於C++中的 Rectangle* rect3 = new Rectangle(*rect2);
編譯運行結果如下圖: