QT與Python混合編程經驗記錄

一、如何embedding python,Python文檔中有專門一章闡述https://docs.python.org/3.5/extending/embedding.htm;html

一、庫文件:在vs--c/c++--附加包含文件中添加目;連接中也要添加,:將python中的include,libs二個目錄添加進來python

二、對於Python,沒有調試庫,可直接將運行庫複製一份,名稱後面加上_d,就可用,可不能源代碼調試而已,同時修改c++

pyconfig.hapi

#ifdef _DEBUG 
//# define Py_DEBUG    //將這行註釋掉
#endif 
app

和object.h函數

#if defined(Py_DEBUG) && !defined(Py_TRACE_REFS) 
// #define Py_TRACE_REFS   //將這行註釋掉
#endif
ui

三、因爲QT中定義了slots做爲關鍵了,而python3中有使用slot做爲變量,因此有衝突,辦法是:spa

  A、在vs中-屬性-c/c++ -預處理器-預處理器定義-中添加:QT_NO_KEYWORDS指令,調試

    在Dt的項目文件中.pro文件中添加 config +=_no_keywords指令,再生成vs的項目文件,也就自動添加了上面的指令orm

    這種方法是全局的,同時也取消 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;  

四、在主程序中執行一開始Py_Initialize(); 時就出現錯誤

   解決辦法是:Py_SetPythonHome((wchar_t*)(L"C:\\Python3"));
是由於我安裝python的時候沒有添加PYTHONHOME這個環境變量
在Py_Initialize()以前調用下Py_SetPythonHome("C:\\Python3");就能夠了 

五、用於導入sys模塊,以供程序使用,這是基本模塊
PyRun_SimpleString("import sys");

六、在執行pModule = PyImport_ImportModule("jptest"); 語句導入自定義模塊時,返回對pModule爲NULL,是因爲自定義模塊的位置不在python系統搜索的系統目錄列表內,所以解決辦法是在系統搜索目錄列表中添加目錄:

PyRun_SimpleString("sys.path.append('D:\\develop\\qtpythontest\\Win32\\Debug')");

注意字符中中"\"必須前面加上「\\",也就是單個"\"是轉意符;並且目錄尾部不能添加多餘的\符;若是不能確承認將它們顯示出來用下面這個語句:PyRun_SimpleString("print(sys.path)");

七、數據轉換,在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);   //這是包含一個字符串元素元組轉換

 

八、調用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); //調用函數
相關文章
相關標籤/搜索