QT與Python混合編程經驗記錄


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); //調用函數
 
        
 
        

 


免責聲明!

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



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