2014-10-06 12 views
0

C++로 작성된 Windows 응용 프로그램이 있습니다. 처리를 위해 python 스크립트에 전달해야하는 문자열 벡터가 있습니다. 간단한 형식으로 C++에서 파이썬을 임베딩하는 방법을 알고 있지만 문자열의 벡터와 동일한 파이썬 개체를 만드는 방법을 살펴 보겠습니다. 내가 좋아하는 뭔가를 찾고 :파이썬을 C++에 임베딩하기. 목록 목록을 수신하는 문자열 전달 벡터

for (size_t i = 0; i < myvector.size(); ++i) 
{ 
    PyUnicode_FromString.append(myvector[i]); 
} 

아니면

for (size_t i = 0; i < myvector.size(); ++i) 
{ 
    pValue = PyUnicode_FromString(myvector[i]); 
    pyTuple_SetItem(myvector.size(), i, pValue); 
} 

벡터 좀처럼 (100 개 항목 최대 내가 말을) 매우 큰 얻을 것이다. 지금은 텍스트 파일을 저장하는 중입니다. 파이썬 스크립트를 열어서 처리하는 것은 분명 좋지 않습니다. 그러나 다른 모든 것이 계획대로 작동한다는 것을 알 수 있습니다. 파이썬 스크립트의 처리는 항목 당 4 개의 값을 생성합니다 (3 개의 문자열과 1 개의 정수 (long)). 또한이 프로그램을 메인 C++ 프로그램으로 돌려 주어야하며, 어떻게해야 될지 잘 모릅니다. (편집) 가능한 옵션을 검토 한 후 목록 목록을 생각하고 있습니다 (사전은 순서가 지정되지 않고 구문 분석 작업이 더 필요합니다) 트릭을 수행해야하지만 C++ 내부에서이 코드를 어떻게 디코딩하는지 알지 못합니다. 프로그램 (다시 한번 지금은 파일 쓰기/읽기로 끝난다. 그래서 나는 그것이 작동한다는 것을 안다). 누구나이 작업을 수행 한 경우 작은 코드 조각을 제공하여 제 요구에 맞출 수 있습니까? 나는 또한 부스트 라이브러리 (그리고 바람직하게는 SWIG도 사용할 수 없다)를 언급해야한다. 그래서 기본적으로 파이썬 C-API로 행해진 다. 내가보기에 서브 프로세스 나 NumPy에 대한 이야기를 본 모든 사례는 내 경우에 (아마도 부정확하게) 적용될 수 있다고 생각하지 않습니다.

답변

1

좋아, 나는 내가 원하는 것을 알아낼 수 있었다. 아래는 내가하려는 일의 예입니다. 그러나 몇 가지 오류 검사가 누락되어 더 중요한 것은 Py_DECREF가 누락되어 답변이 완료되지 않았습니다. 나는 그것을 파악하려고 노력할 것입니다. 그러나 그런 종류의 일에 유창한 누군가가 도울 수 있다면, 그것은 크게 감사 할 것입니다. 여기에 간다 :

Python 스크립트 : (testingoutput.py)이 스크립트는 문자열 목록을 받는다. 각 문자열에 대해 3 개의 임의 문자열 (제공된 목록에서)과 하나의 임의의 정수를 반환한다. 형식 : [[sssi],]

import random 
import string 

def get_list_send_list(*input_list): 
    outer_list = [] 
    for key in input_list:   
     inner_list = [] 
     # from here, your program should produce the data you want to retrieve and insert it in a list 
     # for this example, a list comprised of 3 random strings and 1 random number is returned 
     for i in range (0, 3): 
      some_words = random.choice(["red", "orange", "yellow", "green", "blue", "purple", "white", "black"]) 
      inner_list.append(some_words)   
     inner_list.append(random.randint(1,10)) 
     outer_list.append(inner_list) 
    return outer_list 

그리고 이것은 cpp 파일입니다. Python C API 예제와 거의 같으나 목록을 수정하기 위해 약간 수정되었습니다. 나는 나의 필요를 위해 이것을 필요로하지 않았다. 그러나 나는 그런 종류의 것을 필요로 할 것 같은 누군가의 이익을 위해 여기저기서 몇 가지 타입 체크를했다.

#include <Python.h> 
#include <iostream> 
#include <vector> 

int main(int argc, char *argv[]) 
{ 
    PyObject *pName, *pModule, *pFunc; 
    PyObject *pArgs, *pValue; 
    PyObject *pList, *pListItem, *pyString; 

    char* strarray[] = {"apple", "banana", "orange", "pear"}; 
    std::vector<std::string> strvector(strarray, strarray + 4); 
    std::string pyFile = "testingoutput"; 
    std::string pyFunc = "get_list_send_list"; 

    Py_Initialize(); 
    pName = PyUnicode_FromString(pyFile.c_str()); 
    /* Error checking of pName left out */ 

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

    if (pModule != NULL) 
    { 
     pFunc = PyObject_GetAttrString(pModule, pyFunc.c_str()); 
     /* pFunc is a new reference */ 

     if (pFunc && PyCallable_Check(pFunc)) { 
      pArgs = PyTuple_New(strvector.size()); 
     for (size_t i = 0; i < strvector.size(); ++i) 
      { 
       pValue = PyUnicode_FromString(strvector[i].c_str()); 
       if (!pValue) 
       { 
        Py_DECREF(pArgs); 
        Py_DECREF(pModule); 
        fprintf(stderr, "Cannot convert argument\n"); 
        return 1; 
       } 
       /* pValue reference stolen here: */   
       PyTuple_SetItem(pArgs, i, pValue); 
      }   

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

     if (pValue != NULL) 
     { 
    int py_list_size = PyList_Size(pValue); 
    int sub_list_size = 0; 
    std::cout << "Retrieving content..."<< "\n"; 
    for(Py_ssize_t i = 0; i < py_list_size; ++i) 
    { 
     pList = PyList_GetItem(pValue, i); 
     sub_list_size = PyList_Size(pList); 
     // verify if the subitem is also a list - if yes process it 
     if(PyList_Check(pList)) 
     { 
      std::cout << "********** " << i << " **********\n"; 
      for(Py_ssize_t j = 0; j < sub_list_size; ++j) 
      { 
       pListItem = PyList_GetItem(pList, j); 
       // verify if the item is a string or a number 
       if(PyUnicode_Check(pListItem)) 
       { 
        // "Error ~" does nothing here but it should be defined to catch errors 
        pyString = PyUnicode_AsEncodedString(pListItem, "utf-8", "Error ~"); 
        const char *tmpCstChar = PyBytes_AS_STRING(pyString); 
        std::cout << "Item " << j << ": " << tmpCstChar << "\n"; 
       } 
       else if(PyLong_Check(pListItem)) 
       { 
        int pyNumber = PyLong_AsLong(pListItem); 
        std::cout << "Item " << j << ": " << pyNumber << "\n"; 
       } 
      } 
     } 
     else 
     { 
      std::cout << "This item is not a list\n"; 
     } 
    } 
    Py_DECREF(pValue); 
    } 
      else 
      { 
       Py_DECREF(pFunc); 
       Py_DECREF(pModule); 
       PyErr_Print(); 
       fprintf(stderr,"Call failed\n"); 
       return 1; 
      } 
     } 
     else 
     { 
      if (PyErr_Occurred()) 
       PyErr_Print(); 
      fprintf(stderr, "Cannot find function \"%s\"\n", argv[2]); 
     } 
     Py_XDECREF(pFunc); 
     Py_DECREF(pModule); 
    } 
    else 
    { 
     PyErr_Print(); 
     fprintf(stderr, "Failed to load \"%s\"\n", argv[1]); 
     return 1; 
    } 
    Py_Finalize(); 
    return 0; 
} 

은 다시 몇 가지 오류가 누락 확인하고 훨씬 더 중요한 누락 몇 Py_DECREFs있다. 즉이 프로그램은 메모리 누출입니다. 이 문제를 해결하는 방법을 알고 있다면 도움을받을 수 있습니다.

+0

''ImportError : 파일 이름으로 가져 오기가 지원되지 않습니다. '와 함께'P ' "를로드하지 못했습니다. –