2011-12-08 14 views
9

के साथ एक सी पॉइंटर पास करना मैं पाइथन/सी एपीआई में नया हूं ... मैं अपने सी प्रोग्राम में नई कार्यक्षमता जोड़ने की कोशिश कर रहा हूं, जिसमें मैं इसमें पाइथन एम्बेड कर सकता हूं और साथ ही कार्यक्षमता बढ़ा सकता हूं ताकि एम्बेडेड दुभाषिया एक स्क्रिप्ट निष्पादित कर सकता है जो मेरे सी प्रोग्राम के हिस्से के रूप में लिखे गए एक विस्तारित पायथन मॉड्यूल के साथ बातचीत करेगा। मेरे सी प्रोग्राम में वैश्विक चर नहीं हैं। मैं चीजों को इस तरह रखना चाहता हूं; उसी समय पाइथन के लिए सी कार्यक्षमता का पर्दाफाश करने के लिए, यह प्रोग्राम की स्थिति तक पहुंचने के लिए वैश्विक चर तक पहुंच की आवश्यकता पर विस्तारित सी फ़ंक्शन दिखाई देता है। मैं इसके आसपास कैसे पहुंचू?पायथन/सी एपीआई

उदा। यहाँ कैसे मैं कहाँ PYINTERFACE_Initialize से मुख्य

void PYINTERFACE_Initialize(State *ptr, FILE *scriptFile, const char* scriptFileName) 
{ 
    Py_Initialize(); 
    PyObject *module = Py_InitModule("CInterface", CInterfaceMethods); 
    if (PyRun_SimpleFileEx(scriptFile, scriptFileName, 1) != 0) 
    { 
     printf("PYINTERFACE script execution failed!\n"); 
    } 
    **//ADD State *ptr TO module**  
} 

कहा जाता है embedding पर योजना है यहाँ विस्तारित समारोह है:

static PyObject* 
CInterface_GetStateInfo(PyObject *self, PyObject *args) 
{ 
    const char *printStr; 
    double stateInfo; 
    State *ptr; 

    if(!PyArg_ParseTuple(args, "s", &printStr)) 
    { 
     return NULL; 
    } 
    printf("Received %s\n", printStr); 

    **//RETRIEVE State *ptr FROM self**  

    stateInfo = ptr->info; 
    return Py_BuildValue("d", currentTime); 
} 

* ptr चारों ओर राज्य पारित करने के लिए स्पष्ट तरीका यह है? मैं निश्चित रूप से पाइथन में आंतरिक स्थिति का पर्दाफाश करने की आवश्यकता को नहीं देखता हूं। मैंने कैप्सूल का उपयोग करने के बारे में सोचा, लेकिन ऐसा लगता है कि इस तरह के व्यवहार का समर्थन करने के लिए कैप्सूल का इरादा नहीं है।

अग्रिम धन्यवाद! http://docs.python.org/c-api/capsule.html

मूल रूप से PyCObject: http://docs.python.org/c-api/cobject.html

आप केवल अजगर 2.7 का उपयोग करना चाहते हैं, तो आप एक PyCapsule उपयोग कर सकते हैं: वी

उत्तर

5

यह मानते हुए कि आप कुछ पश्च संगतता चाहते हैं, आप PyCObjects उपयोग करना चाहते हैं सामान आपके अपारदर्शी सूचक को एक पायओब्जेक्ट में परिवर्तित करता है जिसे आप पाइथन के भीतर पास कर सकते हैं और जब आप सी में वापस आते हैं, तो आप इसे खोल सकते हैं और इसका उपयोग कर सकते हैं।

पीई कैप्सूल कुछ विशेषताओं को छोड़कर बहुत समान हैं, मुख्य यह है कि वे आपको कैप्सूल में एक प्रकार की सुरक्षा प्रदान करने के लिए एक प्रकार का स्टोर प्रदान करने की अनुमति देते हैं।

अपने विशिष्ट मामले में, जहां आप सूचक को जोड़ने, तो आप सिर्फ यह (त्रुटि जाँच और विनाश कोड निकाला गया) के लिए करना चाहेंगे में:

PyObject *pystate = PyCObject_FromVoidPtr(State, NULL); 
PyObject *dict = PyModule_GetDict(module); 
PyDict_SetItemString(dict, "CStateObject", pystate); 

# To retrieve it from self (assuming that it is an object) 
PyObject *pystate = PyObject_GetAttrString(self, "CStateObject"); 
State *state = (State *)PyCObject_AsVoidPtr(pystate); 
10

कैप्सूल मूल रूप से अजगर अपारदर्शी शून्य संकेत दिए गए हैं कि आप कर सकते हैं चारों ओर गुजरें या मॉड्यूल के साथ सहयोग करें। वे आपकी समस्या को हल करने के लिए "रास्ता" हैं।

यहां एक उदाहरण है जो एक उदाहरण x का उपयोग करता है जो स्थैतिक नहीं होना चाहिए। सबसे पहले सूचक (समारोह आप कि एक्स सूचक वापस आप कुछ इस तरह करते हैं प्राप्त करने के लिए अजगर को बेनकाब करना चाहते हैं तो फिर इस तरह अपने मॉड्यूल कुछ (त्रुटि हटाया जाँच) को देते हैं ...

// wrap the methods to be exposed to python in a module 
// i.e. this is a list of method descriptions for the module 
static PyMethodDef InitializeTurkeyMethods[] = { 

    // this block describes one method.. turkey.do_something() 
    {"do_something", 
    turkey_do_something, // fn pointer to wrap (defined below) 
    METH_VARARGS, 
    "do something .. return an int."}, 

    {NULL, NULL, 0, NULL} // sentinel. 
}; 


int init(X * x) { 

    // initialize embedded python scripting .. 
    // (this method a no-op on second or later calls). 
    Py_Initialize(); 

    // initialize the turkey python module 
    PyObject * module = Py_InitModule("turkey", InitializeTurkeyMethods); 

    // Create a capsule containing the x pointer 
    PyObject * c_api_object = PyCapsule_New((void *)x, "turkey._X_C_API", NULL); 

    // and add it to the module 
    PyModule_AddObject(module, "_X_C_API", c_api_object); 
} 

इस वास्तव में इससे पहले कि आप उपरोक्त कोड में यह जिक्र शुरू जाना) है:

static PyObject* turkey_do_something(PyObject *self, PyObject *args) {  

    if(!PyArg_ParseTuple(args, ":turkey_do_something")) 
     return NULL; 

    // get the x pointer back from the capsule 
    X * x = (X*)PyCapsule_Import("turkey._X_C_API", 0);  

    // call some fn on x 
    return Py_BuildValue("i", x->some_fn_that_returns_an_int()); 
} 

यहाँ "turkey._X_C_API" बस कुछ जोड़ा प्रकार की जाँच के लिए एक नाम है - अपने अनुप्रयोग के लिए यहाँ में कुछ सार्थक नाम डाल दिया। तुर्की एक डेमो मॉड्यूल नाम है जिसे मैंने अभी बनाया है।के लिए http://docs.python.org/2/c-api/arg.html कैसे:

अब यह सोचते हैं कि, और कैसे, आप turkey_do_something fn जब Py_InitModule बुला निर्यात किया है पर निर्भर करता है() आप इस इस तरह एक अजगर स्क्रिप्ट से कॉल कर सकते हैं:

import turkey 

print turkey.do_something() 

चेक इस tuples प्रारूपित करें और यह .. http://docs.python.org/3.1/c-api/capsule.html कैप्सूल पर डॉको के लिए