2008-10-18 17 views
11

पर डेटा वापस कैसे प्राप्त करें सी ++ प्रोजेक्ट पर काम करते समय, मैं किसी तीसरे पक्ष की लाइब्रेरी की तलाश कर रहा था जो मेरा मुख्य व्यवसाय नहीं है। मुझे वास्तव में अच्छी लाइब्रेरी मिली, जो वास्तव में जरूरी है, लेकिन यह पायथन में लिखा गया है। मैंने Boost.Python लाइब्रेरी का उपयोग कर, C++ में पायथन कोड एम्बेड करने के साथ प्रयोग करने का निर्णय लिया। 'MyFunc':सीपीपी में एम्बेडेड पायथन: सीपीपी

import thirdparty 

def MyFunc(some_arg): 
    result = thirdparty.go() 
    print result 

अब समस्या यह है:

#include <string> 
#include <iostream> 
#include <boost/python.hpp> 

using namespace boost::python; 

int main(int, char **) 
{ 
    Py_Initialize(); 

    try 
    { 
     object module((handle<>(borrowed(PyImport_AddModule("__main__"))))); 

     object name_space = module.attr("__dict__"); 
     object ignored = exec("from myModule import MyFunc\n" 
          "MyFunc(\"some_arg\")\n", 
          name_space); 

     std::string res = extract<std::string>(name_space["result"]); 
    } 
    catch (error_already_set) 
    { 
     PyErr_Print(); 
    } 

    Py_Finalize(); 
    return 0; 
} 

एक (बहुत) सरलीकृत अजगर कोड के संस्करण इस प्रकार है:

सी ++ कोड कुछ इस तरह दिखता ठीक निष्पादित करता है, मैं 'परिणाम' का प्रिंट देख सकता हूं। मैं क्या नहीं कर सकता सी ++ कोड से वापस 'परिणाम' पढ़ा जाता है। निकालने का आदेश कभी भी किसी भी नामस्थान में 'परिणाम' नहीं पाता है। मैंने ग्लोबल के रूप में 'परिणाम' को परिभाषित करने का प्रयास किया, मैंने एक टुपल लौटने का भी प्रयास किया, लेकिन मैं इसे काम नहीं कर सकता।

उत्तर

6

सबसे पहले, अपना कार्य return मान में बदलें। print आईएनजी चीजों को जटिल करेगा क्योंकि आप मूल्य वापस प्राप्त करना चाहते हैं। इस तरह से अपनी MyModule.py दिखता मान लीजिए:

import thirdparty 

def MyFunc(some_arg): 
    result = thirdparty.go() 
    return result 

अब, आप क्या करना चाहते हैं, तो आप, बुनियादी एम्बेडिंग से परे जाने की documentation says के रूप में की है। यहाँ अपने समारोह को चलाने के लिए पूर्ण कोड है:

#include <Python.h> 

int 
main(int argc, char *argv[]) 
{ 
    PyObject *pName, *pModule, *pFunc; 
    PyObject *pArgs, *pArg, *pResult; 
    int i; 

    Py_Initialize(); 
    pName = PyString_FromString("MyModule.py"); 
    /* Error checking of pName left out as exercise */ 

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

    if (pModule != NULL) { 
     pFunc = PyObject_GetAttrString(pModule, "MyFunc"); 
     /* pFunc is a new reference */ 

     if (pFunc) { 
      pArgs = PyTuple_New(0); 
      pArg = PyString_FromString("some parameter") 
      /* pArg reference stolen here: */ 
      PyTuple_SetItem(pArgs, 0, pArg); 
      pResult = PyObject_CallObject(pFunc, pArgs); 
      Py_DECREF(pArgs); 
      if (pResult != NULL) { 
       printf("Result of call: %s\n", PyString_AsString(pResult)); 
       Py_DECREF(pResult); 
      } 
      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"); 
     } 
     Py_XDECREF(pFunc); 
     Py_DECREF(pModule); 
    } 
    else { 
     PyErr_Print(); 
     fprintf(stderr, "Failed to load module"); 
     return 1; 
    } 
    Py_Finalize(); 
    return 0; 
} 
+1

बहुत अधिक व्यापक जवाब का समर्थन नहीं करता एक साथी के माता पिता :) nosklo, मैं सुझाव है कि आप अपने उत्तर को PyRun_String उदाहरण के साथ बढ़ाएं; यह अधिक लचीलापन की अनुमति देता है। – tzot

+0

मुझे लगता है कि आपके 'pArgs = PyTuple_New (0); '1 को 0 पास करना चाहिए। –

0

आपको परिणाम MyFunc से वापस करने में सक्षम होना चाहिए, जो उस चर में समाप्त हो जाएगा जिसे आप वर्तमान में "अनदेखा" कह रहे हैं। यह किसी भी अन्य तरीके से इसे एक्सेस करने की आवश्यकता को समाप्त करता है।

+0

कोई फर्क नहीं पड़ता MyFunc से दिया जाता है, मैं मिलता है: लेखन त्रुटि: 'NoneType' वस्तु से (मुझे लगता है) मद काम, मेरा से –

1

मुझे लगता है कि आपको जो चाहिए वह PyObject_CallObject(<py function>, <args>) है, जो आपके द्वारा PyObject, या PyRun_String(<expression>, Py_eval_input, <globals>, <locals>) के रूप में कॉल किए जाने वाले फ़ंक्शन का रिटर्न वैल्यू देता है जो एक अभिव्यक्ति का मूल्यांकन करता है और इसके परिणाम देता है।

3

ΤΖΩΤΖΙΟΥ, जोश और Nosklo के जवाब पर मैं अंत में यह boost.python का उपयोग कर काम मिला आधार पर:

पायथन:

import thirdparty 

def MyFunc(some_arg): 
    result = thirdparty.go() 
    return result 

सी ++:

#include <string> 
#include <iostream> 
#include <boost/python.hpp> 

using namespace boost::python; 

int main(int, char **) 
{ 
    Py_Initialize(); 

    try 
    { 
     object module = import("__main__"); 
     object name_space = module.attr("__dict__"); 
     exec_file("MyModule.py", name_space, name_space); 

     object MyFunc = name_space["MyFunc"]; 
     object result = MyFunc("some_args"); 

     // result is a dictionary 
     std::string val = extract<std::string>(result["val"]); 
    } 
    catch (error_already_set) 
    { 
     PyErr_Print(); 
    } 

    Py_Finalize(); 
    return 0; 
} 

कुछ महत्वपूर्ण बिंदुओं:

  1. मैं सुविधा से बाहर 'exec_file' को 'कार्यकारी' बदल गया है, यह भी साथ सादे 'Exec' काम करता है। यह अब name_space दो बार पारित करके तय है -
  2. मुख्य कारण यह विफल रहा है कि मैं 'Exec' या 'exec_file' करने के लिए एक "स्थानीय" name_sapce में सफल नहीं हुआ है।
  3. अजगर फ़ंक्शन यूनिकोड तार हैं, वे नहीं परिवर्तनीय करने के लिए 'std :: स्ट्रिंग' कर रहे हैं, तो मैं '.encode (' ASCII ',' उपेक्षा ')' के साथ सभी अजगर तार प्रत्यय करना पड़ा।
संबंधित मुद्दे