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

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

編輯:C++入門知識

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


    在上一篇 C++混合編程之idlcpp教程(一) 中介紹了 idlcpp 工具的使用。現在對 idlcpp 所帶的示例教程進行講解,這裡針對的 Python 語言的例子。首先看第一個示例程序 PythonTutorial0。像很多語言的第一個例子一樣,是一個打印 Hello world 的程序。用Visual Studio 2015打開解決方案文件 tutorials\PythonTutorials\PythonTutorials.sln。其下已經有多個工程文件:

//tutorial $$#include <stdio.h> namespace tutorial { struct Test { static void Run(); }; $* inline void Test::Run() { printf("Hello World!"); } *$ }

和C++代碼較為相似。編譯Tutorial0.i,將會生成Tutorial0.h,Tutorial0.mh,Tutorial0.ic,Tutorial0.mc四個文件。其中Tutorial0.h內容如下:

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

#pragma once


#include <stdio.h>


#line 5 "D:/GitHub/idlcpp/tutorials/Common/Tutorial0.i"
namespace tutorial

#line 6 "D:/GitHub/idlcpp/tutorials/Common/Tutorial0.i"
{

#line 7 "D:/GitHub/idlcpp/tutorials/Common/Tutorial0.i"
    struct Test

#line 8 "D:/GitHub/idlcpp/tutorials/Common/Tutorial0.i"
    {
    public:


#line 9 "D:/GitHub/idlcpp/tutorials/Common/Tutorial0.i"
        static void Run();

#line 10 "D:/GitHub/idlcpp/tutorials/Common/Tutorial0.i"
    };

    inline void Test::Run()
    {
        printf("Hello World!");
    }
    

#line 17 "D:/GitHub/idlcpp/tutorials/Common/Tutorial0.i"
}

因為在編譯.i文件時指定了-ld選項,所以生成的.h文件中其中有許多#line指令,這是為下一步C++編譯時能夠定位錯誤到.i中的位置,而不是定位到.h上。修改編譯選項,去掉-ld選項,重新編譯,得到的結果如下:

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

#pragma once


#include <stdio.h>

namespace tutorial
{
    struct Test
    {
    public:

        static void Run();
    };

    inline void Test::Run()
    {
        printf("Hello World!");
    }
    
}

這樣看起來比較清爽了,請和上面的Tutorial0.i內容對照一下,基本上內容差不多。下面詳細解釋一下,首先是第一行

//tutorial

這是注釋,idlcpp和C++一樣用//表示單行注釋,用/**/表示一塊注釋。

 $$#include <stdio.h>

idlcpp只分析接口的聲明,而C++頭文件中一般還會出現其他的內容。此處idlcpp提供了將.i文件中的部分內容直接復制到.h的方法,一共有三種

這一行表示將#include <stdio.h>復制到.h中,下面的printf要用到這個頭文件。

 

namespace tutorial 以及對應的{}。

namespace 和C++中的概念是一樣的,會原樣輸出到.h中。

 

struct Test 以及對應的{}; 。

這個也和C++中概念類似,會原樣輸出到.h中。

 

下面.h文件中多了一行

public:

在idlcpp中聲明的數據成員以及成員函數都被認為是public的,所以此處無腦加了這一行。

static void Run(); 

這一行兩邊也是一樣的,聲明一個靜態成員函數。

$*

inline void Test::Run()

{

printf("Hello World!");

}

*$

 

如上所述,idlcpp將$*和*$之間的內容復制到.h中。因為idlcpp只處理函數聲明,不能處理其實現代碼,所以無法向C++一樣將其實現代碼放在類的聲明中,只能寫在外面。此處為了少寫一個.cpp文件,就用內聯函數的方式寫在頭文件中。

文件Tutorial0.ic中沒有實質性的內容。

文件Tutorial0.mh和Tutorial0.mc用於構建對應的元數據信息,具體內容牽涉太多,暫時不做解釋。

 再來看一下PythonTutorial0.cpp的內容

#include <tchar.h>
#include <windows.h>
#include "Python.h"
#include "../../../paf/src/pafpython/PythonWrapper.h"
#include "../../Common/Tutorial0.h"
#include "../../Common/Tutorial0.mh"
#include "../../Common/Tutorial0.ic"
#include "../../Common/Tutorial0.mc"


#if defined(_DEBUG)
#pragma comment(lib,"pafcore_d.lib")
#pragma comment(lib,"pafpython_d.lib")
#else
#pragma comment(lib,"pafcore.lib")
#pragma comment(lib,"pafpython.lib")
#endif

int _tmain(int argc, _TCHAR* argv[])
{
    const char* path = "tutorial0";

    PyImport_AppendInittab("pafpython", &PyInit_PafPython);

    Py_Initialize();
    PyObject* pName = PyUnicode_FromString(path);
    PyObject* pModule = PyImport_Import(pName);
    Py_DECREF(pName);
    if(pModule != NULL)
    {
        Py_DECREF(pModule);
    }
    else
    {
        PyErr_Print();
        fprintf(stderr, "Failed to load \"%s\"\n", path);
    }
    Py_Finalize();
     return 0;
}

#include "Python.h"

這一行引入Python頭文件

 

 #include "../../../paf/src/pafpython/PythonWrapper.h"

這一行引入Python插件頭文件

 

#include "../../Common/Tutorial0.h"

#include "../../Common/Tutorial0.mh"

#include "../../Common/Tutorial0.ic"

#include "../../Common/Tutorial0.mc"

 這幾行將由Tutorial0.i編譯的結果包含進來,這樣編譯後就會將對應的元數據信息注冊到系統中,從而能夠讓腳步語言訪問到。

 main()函數中是一個運行一個Python腳步的基本過程。其中

PyImport_AppendInittab("pafpython", &PyInit_PafPython);

這一行在Python中加載插件。

最後看一下tutorial0.py文件的內容

import pafpython;
paf = pafpython.paf;

paf.tutorial.Test.Run();

最後這句代碼表示調用C++中的::tutorial::Test::Run(); 

所有由idlcpp生成的數據類型都是在paf名字下,可以理解為Python中的名字pafpython.paf等價於C++中的全局名字空間。在C++中,Run函數的全名可以認為是::tutorial::Test::Run,在lua中即為pafpython.paf.tutorial.Test.Run。 編譯鏈接後,執行結果如下圖:

可以看到Python正確調用了C++中的函數。

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