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

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

編輯:C++入門知識

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


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

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

與前面的工程相似,工程PythonTutorial3中,同樣加入了三個文件:PythonTutorial3.cpp, Tutorial3.i, tutorial3.py。其中PythonTutorial3.cpp的內容基本和PythonTutorial2.cpp雷同,不再贅述。

首先看一下Tutorial3.i的內容:

namespace tutorial
{
    struct Point
    {
        float x;
        float y;
    meta:
        Point();
        Point(float a, float b);
        Point(const Point ref pt);

        $*
        Point()
        {}
        Point(float a, float b)
        {
            x = a;
            y = b;
        }
        *$
    };

    struct Shape
    {
        abstract float getArea();
        $$        virtual ~Shape() {}
    };

    struct Triangle : Shape
    {
        Point m_vertices[$3];
    meta:
        static Triangle new New();
        $*
            virtual float 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;
        }
        static Triangle* New()
        {
            return new Triangle;
        }
        *$
    };

}


在這裡仍然有struct Point。 引入了基類 struct Shape。其中這一行

abstract float getArea();

表示聲明一個純虛函數,相當於C++中的

virtual float getArea() = 0;

如果不是純虛函數,使用關鍵字virtual代替abstract即可。

新加入了類型 Triangle

struct Triangle : Shape

與C++一樣,用 : 表示繼承。因idlcpp表示的是接口信息,所以只有公有繼承。與C++不同,idlcpp並沒有public, protected, private這三個關鍵字。

然後是數據成員m_vertices;

Point m_vertices[$3];

idlcpp只關心接口的信息,在其語法分析部分,只能看見Point m_vertices[]。數字3需要用插入代碼的方式。其中$表示直接連在後面的一個標識符或整數(實際上是由字母,下劃線和數字組成的串)將插入到生成的C++頭文件對應的位置上。下兩行

meta:

static Triangle new New();

聲明了一個名為New的靜態函數,其實現代碼就在後續的類型聲明內,所以此處用meta阻止在頭文件中生成函數聲明,如前所述,idlcpp如果看見了構造函數的聲明,會生成靜態函數New,所以此時不能出現構造函數的聲明,以免名字沖突。對照一下後面實現部分的C++聲明

static Triangle* New()

這裡和C++不一致的地方是少了一個*並且多了一個new。new是idlcpp中的一個關鍵字,放在函數返回值類型與函數名之間,表示函數內部以new的形式創建了一個對象,返回其指針,外界需要用delete的形式刪除它(還有另一種關於引用計數的情況,暫不討論)。在腳本語言中一般自帶垃圾收集機制,腳本語言自動管理內存的分配釋放。程序員一般不用關心何時刪除對象這樣的問題,而在C++中在堆上分配對象的生命期一般由程序員維護。為處理其間的差異,idlcpp在函數聲明的返回值類型部分有如下幾種形式:

 

idlcpp聲明

C++聲明

實現

typeName

typeName

返回值

typeName ref

typeName&

返回引用

typeName ptr

typeName*

返回指針

typeName new

typeName*

返回指針,外界需要delete,或者增加了引用計數,外界需要release

typeName new []

typeName*

返回指針,外界需要delete[]

例如下面的C++代碼:

 

int g_a;
int* getGlobal()
{
    return &g_a;
}

int* getNew()
{
    return new int;
}

int* getNewArray(int count)
{
    return new int[count];
}

三個函數的返回值類型都是int*,但對於後面兩個,分別要用delete 和delete[]釋放內存,就語法層面看,從函數的聲明不能區分這些情況。只能由程序員根據實際情況進行不同的處理。而在腳本語言中並不希望看到顯示的刪除對象的調用。所以idlcpp通過語法層面的聲明,在生成的元數據代碼中進行區分,然後由運行時庫(pafcore.dll)進行處理。

編譯後生成的Tutorial3.h的內容如下:

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

#pragma once

#include "./Tutorial3.h"
namespace tutorial{ struct Triangle; }

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);
        static Point* Clone(const Point& pt);



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

    struct Shape
    {
    public:

        virtual float getArea() = 0 ;
        virtual ~Shape() {}
    };

    struct Triangle : public Shape
    {
    public:

        Point m_vertices[3];

            virtual float 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;
        }
        static Triangle* New()
        {
            return new Triangle;
        }
        
    };

}

內容基本上都是和Tutorial3.i中一一對應的。

然後看一下腳本tutorial3.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);

print(triangle.getArea()._);

 

創建了一個tirangle對象,然後設置數據成員,此處運行時能夠檢測下標的范圍為0至2,如果超出范圍將會報錯,最後調用其基類Shape中聲明的函數getArea(),因為這是虛函數,所以最終會調用到Traingle::getArea()。

編譯運行結果如下圖:

 

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