2009-09-13 33 views
7

Tôi đang cố gọi một hàm trong một tập lệnh Python từ chương trình C++ chính của tôi. Hàm python lấy một chuỗi làm đối số và trả về không có gì (ok .. 'None'). Nó hoạt động hoàn toàn tốt (không bao giờ nghĩ rằng nó sẽ được dễ dàng ..) miễn là cuộc gọi trước đó được hoàn thành trước khi chức năng được gọi lại, nếu không có một sự vi phạm truy cập tại pModule = PyImport_Import(pName).Gọi Python từ C++

Có rất nhiều hướng dẫn cách nhúng python vào C và ngược lại nhưng tôi không tìm thấy gì về vấn đề đó.

int callPython(TCHAR* title){ 
    PyObject *pName, *pModule, *pFunc; 
    PyObject *pArgs, *pValue; 

Py_Initialize(); 
    pName = PyUnicode_FromString("Main"); 
    /* Name of Pythonfile */ 

    pModule = PyImport_Import(pName); 
    Py_DECREF(pName); 

if (pModule != NULL) { 
     pFunc = PyObject_GetAttrString(pModule, "writeLyricToFile"); 
     /* function name. pFunc is a new reference */ 
     if (pFunc && PyCallable_Check(pFunc)) { 
      pArgs = PyTuple_New(1); 

    pValue = PyUnicode_FromWideChar(title, -1); 

    if (!pValue) { 
     Py_DECREF(pArgs); 
       Py_DECREF(pModule); 
     showErrorBox(_T("pValue is false")); 
     return 1; 
      } 
    PyTuple_SetItem(pArgs, 0, pValue); 

      pValue = PyObject_CallObject(pFunc, pArgs); 
      Py_DECREF(pArgs); 

      if (pValue != NULL) { 
       //worked as it should! 
       Py_DECREF(pValue); 
      } 
      else { 
       Py_DECREF(pFunc); 
       Py_DECREF(pModule); 
       PyErr_Print(); 
     showErrorBox(_T("pValue is null")); 
     return 1; 
      } 
     } 
     else { 
      if (PyErr_Occurred()) PyErr_Print(); 
      showErrorBox(_T("pFunc null or not callable")); 
     return 1; 
     } 
     Py_XDECREF(pFunc); 
     Py_DECREF(pModule); 
    } 
    else { 
     PyErr_Print(); 
     showErrorBox(_T("pModule is null")); 
    return 1; 
    } 
    Py_Finalize(); 
    return 0; 
} 

Trả lời

5

Khi bạn nói "miễn là cuộc gọi trước được kết thúc trước khi hàm được gọi lại", tôi chỉ có thể giả định rằng bạn có nhiều chủ đề gọi từ C++ sang Python. Các python không phải là thread an toàn, vì vậy điều này sẽ thất bại!

Đọc trên Khóa thông dịch toàn cầu (GIL) trong hướng dẫn sử dụng Python. Có lẽ các liên kết dưới đây sẽ giúp:

Các GIL được đề cập trên Wikipedia:

1

Cảm ơn sự giúp đỡ của bạn!

Có bạn nói đúng, có một vài chủ đề C. Không bao giờ nghĩ rằng tôi cần mutex cho người phiên dịch - GIL là một khái niệm hoàn toàn mới cho tôi (và thậm chí không được nhắc đến một lần trong toàn bộ hướng dẫn).

Sau khi đọc các tài liệu tham khảo (chắc chắn không phải là phần dễ nhất của nó, mặc dù PyGILState_ * chức năng đơn giản hóa toàn bộ điều rất nhiều), tôi đã thêm một chức năng

void initPython(){ 
    PyEval_InitThreads(); 
    Py_Initialize(); 
    PyEval_ReleaseLock(); 
} 

để khởi sự phiên dịch chính xác. Mỗi chuỗi tạo cấu trúc dữ liệu của nó, mua lại khóa và giải phóng nó sau đó như được hiển thị trong tham chiếu.

Làm việc như nó cần, nhưng khi gọi Py_Finalize() trước khi chấm dứt quá trình tôi nhận được một segfault .. bất kỳ vấn đề với chỉ cần rời khỏi nó?

+2

Tôi rất vui vì điều này đã khắc phục được sự cố của bạn. Tôi không thể nghĩ tại sao bạn có vấn đề gọi Py_Finalize() - có lẽ bạn có thể cung cấp một ví dụ đơn giản cho thấy vấn đề trong câu hỏi khác. Bạn thực sự nên tắt Python một cách rõ ràng, nhưng nếu bạn chỉ muốn thoát khỏi ứng dụng, bạn có thể ổn ... Tôi mạnh mẽ khuyên bạn nên tìm ra lý do tại sao nó bị treo. –

+0

@DanielPaull bạn có thể vui lòng cho một ví dụ làm việc đơn giản cho cùng một chủ đề trên. Vì vậy, tôi có thể hiểu dễ dàng – lkkkk