此文拋磚引玉,僅作記錄,希望廣大網友多多指正,謝謝!
最近接觸了混編的項目,項目是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混合編程操作的例子:
一、環境搭建
- 安裝python2.7(其他版本的python環境不影響下面的操作,只是注意區分不同的設置)。
- 配置vs2013項目(python自帶的python27.dll為release版本,所以vs2013項目也必須調整為release,如果需要debug版本可以下載python源碼自己編譯,也可以在網上找找有沒有好心人編譯好的。)
- 使用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 }
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方式,這種方式目前沒有做過嘗試,放在下一篇繼續記錄我的實踐操作吧,感謝大家的支持!