1、如何embedding python,Python文檔中有專門一章闡述https://docs.python.org/3.5/extending/embedding.htm;
1、庫文件:在vs--c/c++--附加包含文件中添加目;鏈接中也要添加,:將python中的include,libs二個目錄添加進來
2、對於Python,沒有調試庫,可直接將運行庫復制一份,名稱后面加上_d,就可用,可不能源代碼調試而已,同時修改
pyconfig.h
#ifdef _DEBUG
//# define Py_DEBUG //將這行注釋掉
#endif
和object.h
#if defined(Py_DEBUG) && !defined(Py_TRACE_REFS)
// #define Py_TRACE_REFS //將這行注釋掉
#endif
3、由於QT中定義了slots作為關鍵了,而python3中有使用slot作為變量,所以有沖突,辦法是:
A、在vs中-屬性-c/c++ -預處理器-預處理器定義-中添加:QT_NO_KEYWORDS指令,
在Dt的項目文件中.pro文件中添加 config +=_no_keywords指令,再生成vs的項目文件,也就自動添加了上面的指令
這種方法是全局的,同時也取消 forever,foreach的宏定義,因為很多代碼使用foreach,所以副作用大;
B、在使用第三方代碼時暫時取消沖突的宏定義,然后重新定義相關宏,如QT調用第三方python時,只是在python的object.h中 slots沖突,因此修改object.h:
typedef struct{
const char* name;
int basicsize;
int itemsize;
unsigned int flags;
#undef slots //這里取消slots宏定義
PyType_Slot *slots; /* terminated by slot==0. */
#define slots Q_SLOTS //這里恢復slots宏定義與QT中QObjectDefs.h中一致
} PyType_Spec;
4、在主程序中執行一開始Py_Initialize(); 時就出現錯誤
解決辦法是:Py_SetPythonHome((wchar_t*)(L"C:\\Python3"));
是因為我安裝python的時候沒有添加PYTHONHOME這個環境變量
在Py_Initialize()之前調用下Py_SetPythonHome("C:\\Python3");就可以了
5、用於導入sys模塊,以供程序使用,這是基本模塊
PyRun_SimpleString("import sys");
6、在執行pModule = PyImport_ImportModule("jptest"); 語句導入自定義模塊時,返回對pModule為NULL,是由於自定義模塊的位置不在python系統搜索的系統目錄列表內,因此解決辦法是在系統搜索目錄列表中添加目錄:
PyRun_SimpleString("sys.path.append('D:\\develop\\qtpythontest\\Win32\\Debug')");
注意字符中中"\"必須前面加上“\\",也就是單個"\"是轉意符;而且目錄尾部不能添加多余的\符;如果不能確認可將它們顯示出來用下面這個語句:PyRun_SimpleString("print(sys.path)");
7、數據轉換,在c/c++與python交互時,都是通過PyObject來傳入和傳出數據的,Python提供相關函數對PyObject數據進行轉換,轉換時使用格式字符串來控制生成的對象類型,具體可參見https://docs.python.org/3.5/c-api/arg.html官方文檔:
A) 將c/c++數據轉換成PyObject:
PyObject *pInt=Py_BuildValue("i",2003);
PyObject *pStr=Py_BuildValue("s","This is a string");
PyObject *pTuples=Py_BuildValue("()"); //生成空元組,可作為調用不包含任何參數的函數時,傳遞空參數
PyObject *pTuples=Py_BuildValue("(s)","This is a string"); //生成一個元素的元組,可作為調用只包含一個字符參數的函數時,傳遞一個字符參數
B) 將PyObject數據轉換成c/c++數據:
1) int bb=0; PyArg_Parse(pObjcet,"i",&bb); //這里pObject是包含整數數據的Python對象,第二個字符串參數"i"指定轉換類型,第三個參數將結果值存入bb變量;
2) char * cc=NULL; PyArg_parse(pObject,"s",&cc); //這是字符串轉換
3) char * cc=NULL; PyArg_parse(pObject,"(s)",&cc); //這是包含一個字符串元素元組轉換
8、調用Python模塊函數時,傳入參數時,要構造一個參數元組,如:presult = PyObject_CallObject(pfunction, args);這里args就是一個元組,作為被調用函數的參數列表;
A、如參數為空,則這樣構造:args=Py_BuildValues("(si)","abc",10); 表示構造二個參數的元組,一個是字符型,另一個是整;多個參數,可參照處;
B、如果參數為空,則需構造一個包含0個元素元組:args=Py_BuildValues("()");
注意以上二種都在格式字符串中包含"()",這是指示構造元;作為函數調用參數必須傳遞元組,也必須這樣構;
下例是通過可變參數來構造調用函數參數元組:
int PythonHandler::PyModuleRunFunction(const char *module, const char *function,
const char *result_format, void *result, const char *args_format, ...) {
......
//這里構造調用函數所使用的參數元組
va_list args_list; va_start(args_list, args_format); args = Py_VaBuildValue(const_cast<char *>(args_format), args_list); va_end(args_list);
...
if (!args)
{
//args為空,則元組構造失敗
Py_DECREF(pfunction);
return -3;
}
...
presult = PyObject_CallObject(pfunction,args); //調用函數