混合編程雜談


  此文拋磚引玉,僅作記錄,希望廣大網友多多指正,謝謝!

  最近接觸了混編的項目,項目是02年開發的,當時使用的是VC6.0+TCL腳本,VC負責前台的界面顯示,后台全部用TCL實現,由於公司規定不能截圖出來,望大家海涵,大概描述一下工具的功能,主要用於檢查某種負責通信的服務是否配置、運行等正常。大體功能如下:左邊是局點的控制描述,主要記錄有局點名稱、局點IP、連接方式、用戶名密碼、是否使用內置FTP等信息,右邊是每一個局點要執行的任務配置項,主要分為兩個大項:健康檢查和信息收集。

  最近有一個新的需求是給現有的工具添加一個導入導出的功能,主要就是左邊的這些操作,方便在配置一次后,在不同的PC上運行相同的工具不需要重新再次配置,只需要將要來配置好的執行一次導入導出就可以執行檢查操作。由於本人再次之前沒有接觸過VC的MFC框架,所以想通過其他的方式處理這個新的需求,目前在網上找到一些可以參考的例子:

  C++與python混合編程

  • (http://blog.sina.com.cn/s/blog_6ec980ee0101cgax.html)
  • (http://www.cnblogs.com/lvpengms/archive/2010/02/03/1663071.html)
  • (http://www.cnblogs.com/yincheng01/archive/2010/04/24/2213259.html)

  java和jpython混合編程

  • (http://blog.csdn.net/hong0220/article/details/40831605)

  C#與python混合編程

  • (http://www.cnblogs.com/chaosimple/p/4035693.html)

  但是看起在運行的過程中都離不開python解釋器,這讓人很頭疼也很郁悶呀,因為我不能要求需要使用這個工具的的人都安裝python的解釋器,而且不同的人安裝的解釋器版本不同,有可能出現更多的問題,這些都不是我一個小小的開發能控制的。所以我的想法是我能不能把python的運行環境集成起來形成一個封閉的工具系統而不依賴具體的環境,就像是java開發的軟件獨立的攜帶自己的jvm獨立運行。

  找到一個C++與python混合編程操作的例子:

  一、環境搭建

  1. 安裝python2.7(其他版本的python環境不影響下面的操作,只是注意區分不同的設置)
  2. 配置vs2013項目(python自帶的python27.dllrelease版本,所以vs2013項目也必須調整為release,如果需要debug版本可以下載python源碼自己編譯,也可以在網上找找有沒有好心人編譯好的。
  3. 使用VS2013創建C++工程,創建完成后設置工程的屬性引用頭文件和靜態庫等,具體設置如下圖所示:

  ① C/C++  ----> 常規 ---> 附件庫包含目錄,加入python頭文件目錄

 

  ② 連接器 ---> 常規 --->附件庫目錄。加入python庫文件目錄

 

  ③ 連接器 ---> 輸入 ---> 附加依賴項。加入python庫文件名

 

  二、代碼實現

  1、嵌套調用

  1 // test_C_python.cpp : 定義控制台應用程序的入口點。
  2 //
  3 
  4 #include "stdafx.h"
  5 #include "Python.h"
  6 #include <iostream>  
  7 
  8 using namespace std;
  9 
 10 void script_fun()
 11 {
 12     Py_Initialize();                             /* Python解釋器初始化 */
 13     PyRun_SimpleString("print \"hi,python!\"");        /* 運行python字符串 */
 14     Py_Finalize();                                /* 結束Python解釋器,釋放資源 */
 15 }
 16 
 17 void HelloWorld();
 18 void Add();
 19 void TestTransferDict();
 20 void TestClass();
 21 
 22 int _tmain(int argc, _TCHAR* argv[])
 23 {
 24     //直接運行python的執行語句
 25     script_fun();
 26     //C_python_fun();
 27     cout << "Starting Test..." << endl;
 28     cout << "HelloWorld()-------------" << endl;
 29     HelloWorld();
 30     cout << "Add()--------------------" << endl;
 31     Add();
 32     cout << "TestDict-----------------" << endl;
 33     TestTransferDict();
 34     cout << "TestClass----------------" << endl;
 35     TestClass();
 36     system("pause");
 37     return 0;
 38 }
 39 
 40 //調用輸出"Hello World"函數  
 41 void HelloWorld()
 42 {
 43     Py_Initialize();              //使用python之前,要調用Py_Initialize();這個函數進行初始化  
 44     PyObject * pModule = NULL;    //聲明變量  
 45     PyObject * pFunc = NULL;      //聲明變量  
 46     pModule = PyImport_ImportModule("pytest");              //這里是要調用的Python文件名  
 47     pFunc = PyObject_GetAttrString(pModule, "HelloWorld");   //這里是要調用的函數名  
 48     PyEval_CallObject(pFunc, NULL);                         //調用函數,NULL表示參數為空  
 49     Py_Finalize();                //調用Py_Finalize,這個和Py_Initialize相對應的.  
 50 }
 51 
 52 //調用Add函數,傳兩個int型參數  
 53 void Add()
 54 {
 55     Py_Initialize();
 56     PyObject * pModule = NULL;
 57     PyObject * pFunc = NULL;
 58     pModule = PyImport_ImportModule("pytest");      //pytest:Python文件名  
 59     pFunc = PyObject_GetAttrString(pModule, "add");  //Add:Python文件中的函數名  
 60     //創建參數:  
 61     PyObject *pArgs = PyTuple_New(2);               //函數調用的參數傳遞均是以元組的形式打包的,2表示參數個數  
 62     PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", 5));//0---序號  i表示創建int型變量  
 63     PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", 7));//1---序號  
 64     //返回值  
 65     PyObject *pReturn = NULL;
 66     pReturn = PyEval_CallObject(pFunc, pArgs);      //調用函數  
 67     //將返回值轉換為int類型  
 68     int result;
 69     PyArg_Parse(pReturn, "i", &result);    //i表示轉換成int型變量  
 70     cout << "5+7 = " << result << endl;
 71     Py_Finalize();
 72 }
 73 
 74 //參數傳遞的類型為字典  
 75 void TestTransferDict()
 76 {
 77     Py_Initialize();
 78     PyObject * pModule = NULL;
 79     PyObject * pFunc = NULL;
 80     pModule = PyImport_ImportModule("pytest");      //pytest:Python文件名  
 81     pFunc = PyObject_GetAttrString(pModule, "TestDict"); //Add:Python文件中的函數名  
 82     //創建參數:  
 83     PyObject *pArgs = PyTuple_New(1);
 84     PyObject *pDict = PyDict_New();   //創建字典類型變量  
 85     PyDict_SetItemString(pDict, "Name", Py_BuildValue("s", "WangYao")); //往字典類型變量中填充數據  
 86     PyDict_SetItemString(pDict, "Age", Py_BuildValue("i", 25));         //往字典類型變量中填充數據  
 87     PyTuple_SetItem(pArgs, 0, pDict);//0---序號  將字典類型變量添加到參數元組中  
 88     //返回值  
 89     PyObject *pReturn = NULL;
 90     pReturn = PyEval_CallObject(pFunc, pArgs);      //調用函數  
 91     //處理返回值:  
 92     int size = PyDict_Size(pReturn);
 93     cout << "返回字典的大小為: " << size << endl;
 94     PyObject *pNewAge = PyDict_GetItemString(pReturn, "Age");
 95     int newAge;
 96     PyArg_Parse(pNewAge, "i", &newAge);
 97     cout << "True Age: " << newAge << endl;
 98     Py_Finalize();
 99 }
100 
101 //測試類  
102 void TestClass()
103 {
104     Py_Initialize();
105     PyObject * pModule = NULL;
106     PyObject * pFunc = NULL;
107     pModule = PyImport_ImportModule("pytest");      //pytest:Python文件名  
108     pFunc = PyObject_GetAttrString(pModule, "TestDict"); //Add:Python文件中的函數名  
109     //獲取Person類  
110     PyObject *pClassPerson = PyObject_GetAttrString(pModule, "Person");
111     //創建Person類的實例  
112     PyObject *pInstancePerson = PyInstance_New(pClassPerson, NULL, NULL);
113     //調用方法  
114     PyObject_CallMethod(pInstancePerson, "greet", "s", "Hello Kitty");   //s表示傳遞的是字符串,值為"Hello Kitty"  
115     Py_Finalize();
116 }
C++代碼調用python
 1 #!/usr/bin/python
 2 # -*- coding: utf-8 -*-
 3 
 4 def Hello(s):
 5     print "Hello, world!"
 6     print s
 7 
 8 def HelloWorld():  
 9     print "Hello World"  
10 def add(a, b):  
11     return a+b  
12 def TestDict(dict):  
13     print dict  
14     dict["Age"] = 17  
15     return dict  
16 class Person:  
17     def greet(self, greetStr):  
18         print greetStr  
19 #print add(5,7)  
20 #a = raw_input("Enter To Continue...")  

運行結果:

 

  2、Python調用C++(使用python中的ctypes模塊可以很方便的調用windows的dll(也包括linux下的so等文件))

1 from ctypes import *
2 dll = CDLL("add.dll")  
3 print dll.Add(1, 102) 

還有一種方式是利用boost庫中的,boost.python方式,這種方式目前沒有做過嘗試,放在下一篇繼續記錄我的實踐操作吧,感謝大家的支持!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM