2009-06-28 22 views
32

मैं कुछ नई कार्यक्षमता के साथ एक बड़ी सी परियोजना का विस्तार करना चाहता हूं, लेकिन मैं वास्तव में इसे पायथन में लिखना चाहता हूं। असल में, मैं सी कोड से पायथन कोड को कॉल करना चाहता हूं। हालांकि, पायथन-> एसपीआईजी जैसे सी रैपर OPPOSITE के लिए अनुमति देते हैं, जो सी मॉड्यूल लिख रहा है और पायथन से सी को कॉल कर रहा है।आप सी कोड से पायथन कोड कैसे कॉल करते हैं?

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

अभी तक उत्तर के लिए धन्यवाद - हालांकि, मैं आईपीसी आधारित दृष्टिकोण पर ध्यान केंद्रित करना चाहता हूं क्योंकि मैं अपने सी प्रोग्राम के रूप में एक अलग प्रक्रिया में अपना पायथन कार्यक्रम रखना चाहता हूं। मैं एक पायथन दुभाषिया एम्बेड नहीं करना चाहता हूँ। धन्यवाद!

+5

एक अलग प्रक्रिया में अजगर कार्यक्रम डाल करने के लिए इच्छुक है, और एक अजगर दुभाषिया एम्बेड करने के लिए नहीं चाहते के लिए अपने तर्क क्या है? मैं उत्सुक हूँ। –

+1

ठीक है अगर वह पाइथन के लिए केवल पाइपिंग तारों के साथ एक रास्ता प्राप्त कर सकता है और फिर जब इसे पूरा किया जाता है तो उसे वापस पाइथन दुभाषिया एम्बेड करने से बहुत आसान लगता है। इंटरफ़ेस सरल है (बस स्ट्रिंग्स और तारों को पार करते हैं) को बस एक अलग पायथन ऐप को कॉल करने के लिए 5 मिनट के एकीकरण की आवश्यकता होगी और मुझे यकीन है कि एक दुभाषिया को एम्बेड करने में 5 मिनट से अधिक समय लगेगा – hhafez

+0

यहां एक पूर्ण उदाहरण https: // स्टैक ओवरफ़्लो।कॉम/ए/46441794/5842403 जहां आप सी में एम्बेडेड पायथन देख सकते हैं, और फिर सीपीआई का उपयोग कर Systemverilog में एम्बेडेड सी। – Joniale

उत्तर

10

मैं approaches detailed here की अनुशंसा करता हूं। यह पाइथन कोड के तारों को निष्पादित करने के बारे में बताते हुए शुरू होता है, फिर वहां से विवरण बताएं कि आपके सी प्रोग्राम से बातचीत करने के लिए पाइथन पर्यावरण कैसे स्थापित करें, अपने सी कोड से पायथन फ़ंक्शन को कॉल करें, अपने सी कोड आदि से पाइथन ऑब्जेक्ट्स में हेरफेर करें।

EDIT: यदि आप वास्तव में आईपीसी के मार्ग पर जाना चाहते हैं, तो आप the struct module या बेहतर अभी तक protlib का उपयोग करना चाहेंगे। पाइथन और सी प्रक्रिया के बीच अधिकतर संचार आगे बढ़ने वाले चारों ओर घूमते हैं, या तो over a socket या shared memory के माध्यम से।

मैं आदेशों और उनके तर्कों का प्रतिनिधित्व करने के लिए फ़ील्ड और कोड के साथ Command संरचना बनाने की अनुशंसा करता हूं। मैं जो हासिल करना चाहता हूं उसके बारे में अधिक जानने के बिना मैं अधिक विशिष्ट सलाह नहीं दे सकता, लेकिन आम तौर पर मैं protlib लाइब्रेरी की अनुशंसा करता हूं, क्योंकि मैं सी और पायथन प्रोग्राम के बीच संवाद करने के लिए उपयोग करता हूं (अस्वीकरण: मैं प्रोट्लिब का लेखक हूं) ।

+1

मैंने पहले यह किया है और यह अच्छी तरह से काम किया है। मेरे पास कई सी प्रक्रियाएं थीं जो सॉकेट पर structs भेजकर संचारित थीं और पाइथन प्रक्रियाओं को भी अनुमति देना चाहती थीं। प्रोटोकॉल सामान लिखना पायथन में छोटा था और मैं एक पायथन स्क्री लिखने में सक्षम था जो कि पायथन कोड को स्वत: संसाधित करने के लिए निर्माण के हिस्से के रूप में भाग गया था। एच फाइलों को पार्स करके सी structs को पैक/अनपैक करने के लिए। केवल समस्या सभी स्ट्रिंग पैकिंग/अनपॅकिंग के कारण होती है, प्रदर्शन लगभग मूलभूत सी के साथ प्राप्त नहीं होता है जो सीधे स्ट्रक्चर के द्विआधारी प्रतिनिधित्व पर काम करता है और सॉकेट से कच्चे डेटा कास्टिंग करता है। – bdk

4

के मैनुअल में प्रासंगिक अध्याय देखें: http://docs.python.org/extending/

अनिवार्य रूप से आप अपने कार्यक्रम में अजगर दुभाषिया एम्बेड करने के लिए होगा।

4

क्या आपने अभी अपने पाइथन एप्लिकेशन को शेल स्क्रिप्ट में लपेट लिया है और इसे अपने सी एप्लिकेशन में से आमंत्रित किया है?

सबसे सुरुचिपूर्ण समाधान नहीं है, लेकिन यह बहुत आसान है।

+0

वास्तव में यदि वह एक अलग प्रक्रिया में पायथन चलाने के लिए और stdin/stdio पर बात करना चाहता है, तो यह केवल सबसे अच्छा समाधान है। – Crashworks

1

मैंने पायथन < -> सी संचार के लिए आईपीसी दृष्टिकोण का उपयोग नहीं किया है, लेकिन इसे बहुत अच्छी तरह से काम करना चाहिए। मेरे पास सी प्रोग्राम एक मानक कांटा-निष्पादन करेगा और संचार के लिए बाल प्रक्रिया में रीडायरेक्ट stdin और stdout का उपयोग करेगा। एक अच्छा टेक्स्ट-आधारित संचार पाइथन प्रोग्राम को विकसित और परीक्षण करना बहुत आसान बना देगा।

+0

विंडोज पर फोर्क-निष्पादन संभव है? निश्चित नहीं है कि प्रश्नकर्ता का मंच क्या है। –

+0

विंडोज के तहत कांटा-निष्पादन करने के लिए एक (मुश्किल) दस्तावेज तरीका है, लेकिन मैं वहां नहीं करूँगा। उन्होंने यूनिक्स सॉकेट का उल्लेख किया ताकि मैं मान रहा हूं कि लक्ष्य विंडोज नहीं है। मुझे लगता है कि यह विंडोज के तहत स्पॉन और पाइप की तरह होगा। –

1

अगर मैं भारतीय दंड संहिता के साथ जाने का फैसला किया था मैं शायद XML-RPC साथ शेख़ी चाहते हैं, -, पार मंच आप आसानी से एक अलग नोड पर अजगर सर्वर परियोजना डाल बाद में अगर आप चाहते हैं की सुविधा देता है, कई उत्कृष्ट कार्यान्वयन (here देखना है सरल एक्सएमएल-आरपीसी सर्वर के लिए सी और पायथन वाले, और here सहित कई लोगों के लिए, जो कि पाइथन मानक लाइब्रेरी का हिस्सा है - अन्य दृष्टिकोणों के रूप में अत्यधिक स्केलेबल नहीं है लेकिन संभवतः आपके उपयोग के मामले के लिए ठीक और सुविधाजनक है)।

यह सभी मामलों के लिए एक आदर्श आईपीसी दृष्टिकोण नहीं हो सकता है (या यहां तक ​​कि एक आदर्श आरपीसी एक, हर तरह से!), लेकिन सुविधा, लचीलापन, मजबूती, और कार्यान्वयन की विस्तृत श्रृंखला मेरी राय में बहुत से मामूली दोषों से अधिक है।

0

जाहिरा तौर पर पायथन Win32 dll को संकलित करने के लिए सक्षम होना चाहिए, यह समस्या

का समाधान होगा इस तरह से है कि Win32 DLLs के लिए सी # कोड परिवर्तित यह किसी भी विकास उपकरण

+1

यह केवल Win32 प्लेटफॉर्म पर लागू होता है :-p यूनिक्स के बारे में क्या? – Pharaun

0

यह लगता है के द्वारा प्रयोग करने योग्य कर देगा काफी अच्छा http://thrift.apache.org/, इसके बारे में भी एक किताब है।

विवरण:

अपाचे बचत सॉफ्टवेयर ढांचे, स्केलेबल पार भाषा सेवाओं के विकास के लिए, एक सॉफ्टवेयर स्टैक एक कोड पीढ़ी के साथ सेवाओं है कि सी ++ के बीच कुशलतापूर्वक और समेकित रूप से काम का निर्माण करने के इंजन को जोड़ती है, जावा , पायथन, पीएचपी, रूबी, एरलांग, पर्ल, हास्केल, सी #, कोको, जावास्क्रिप्ट, नोड.जेएस, स्मॉलटाक, ओकैमल और डेल्फी और अन्य भाषाओं।

0

मैंने Embedding Python in Another Application के "मानक" दृष्टिकोण का उपयोग किया है। लेकिन यह जटिल/थकाऊ है। पाइथन में प्रत्येक नया कार्य लागू करने के लिए दर्दनाक है।

मैंने Calling PyPy from C का एक उदाहरण देखा। यह इंटरफेस को सरल बनाने के लिए सीएफएफआई का उपयोग करता है लेकिन इसे पायपी की आवश्यकता नहीं है, पाइथन। कम से कम एक उच्च स्तर पर, पहले इस उदाहरण को पढ़ें और समझें।

मैंने पायथन के साथ काम करने के लिए सी/पीईपीई उदाहरण को संशोधित किया। सीएफएफआई का उपयोग कर सी से पायथन को कॉल करने का तरीका यहां दिया गया है।

मेरा उदाहरण अधिक जटिल है क्योंकि मैंने एक के बजाय पायथन में तीन कार्यों को लागू किया है। मैं आगे और आगे डेटा पास करने के अतिरिक्त पहलुओं को कवर करना चाहता था।

जटिल भाग अब api के पते को पाइथन में पास करने के लिए अलग है। केवल एक बार लागू किया जाना है। उसके बाद पायथन में नए कार्यों को जोड़ना आसान है।

interface.h

// These are the three functions that I implemented in Python. 
// Any additional function would be added here. 
struct API { 
    double (*add_numbers)(double x, double y); 
    char* (*dump_buffer)(char *buffer, int buffer_size); 
    int (*release_object)(char *obj); 
}; 

test_cffi.c

// 
// Calling Python from C. 
// Based on Calling PyPy from C: 
// http://doc.pypy.org/en/latest/embedding.html#more-complete-example 
// 

#include <stdio.h> 
#include <assert.h> 

#include "Python.h" 

#include "interface.h" 

struct API api; /* global var */ 

int main(int argc, char *argv[]) 
{ 
    int rc; 

    // Start Python interpreter and initialize "api" in interface.py using 
    // old style "Embedding Python in Another Application": 
    // https://docs.python.org/2/extending/embedding.html#embedding-python-in-another-application 
    PyObject *pName, *pModule, *py_results; 
    PyObject *fill_api; 
#define PYVERIFY(exp) if ((exp) == 0) { fprintf(stderr, "%s[%d]: ", __FILE__, __LINE__); PyErr_Print(); exit(1); } 

    Py_SetProgramName(argv[0]); /* optional but recommended */ 
    Py_Initialize(); 
    PyRun_SimpleString(
      "import sys;" 
      "sys.path.insert(0, '.')"); 

    PYVERIFY(pName = PyString_FromString("interface")) 
    PYVERIFY(pModule = PyImport_Import(pName)) 
    Py_DECREF(pName); 
    PYVERIFY(fill_api = PyObject_GetAttrString(pModule, "fill_api")) 

    // "k" = [unsigned long], 
    // see https://docs.python.org/2/c-api/arg.html#c.Py_BuildValue 
    PYVERIFY(py_results = PyObject_CallFunction(fill_api, "k", &api)) 
    assert(py_results == Py_None); 

    // Call Python function from C using cffi. 
    printf("sum: %f\n", api.add_numbers(12.3, 45.6)); 

    // More complex example. 
    char buffer[20]; 
    char * result = api.dump_buffer(buffer, sizeof buffer); 
    assert(result != 0); 
    printf("buffer: %s\n", result); 

    // Let Python perform garbage collection on result now. 
    rc = api.release_object(result); 
    assert(rc == 0); 

    // Close Python interpreter. 
    Py_Finalize(); 

    return 0; 
} 

interface.py

import cffi 
import sys 
import traceback 

ffi = cffi.FFI() 
ffi.cdef(file('interface.h').read()) 

# Hold references to objects to prevent garbage collection. 
noGCDict = {} 

# Add two numbers. 
# This function was copied from the PyPy example. 
@ffi.callback("double (double, double)") 
def add_numbers(x, y): 
    return x + y 

# Convert input buffer to repr(buffer). 
@ffi.callback("char *(char*, int)") 
def dump_buffer(buffer, buffer_len): 
    try: 
     # First attempt to access data in buffer. 
     # Using the ffi/lib objects: 
     # http://cffi.readthedocs.org/en/latest/using.html#using-the-ffi-lib-objects 
     # One char at time, Looks inefficient. 
     #data = ''.join([buffer[i] for i in xrange(buffer_len)]) 

     # Second attempt. 
     # FFI Interface: 
     # http://cffi.readthedocs.org/en/latest/using.html#ffi-interface 
     # Works but doc says "str() gives inconsistent results". 
     #data = str(ffi.buffer(buffer, buffer_len)) 

     # Convert C buffer to Python str. 
     # Doc says [:] is recommended instead of str(). 
     data = ffi.buffer(buffer, buffer_len)[:] 

     # The goal is to return repr(data) 
     # but it has to be converted to a C buffer. 
     result = ffi.new('char []', repr(data)) 

     # Save reference to data so it's not freed until released by C program. 
     noGCDict[ffi.addressof(result)] = result 

     return result 
    except: 
     print >>sys.stderr, traceback.format_exc() 
     return ffi.NULL 

# Release object so that Python can reclaim the memory. 
@ffi.callback("int (char*)") 
def release_object(ptr): 
    try: 
     del noGCDict[ptr] 
     return 0 
    except: 
     print >>sys.stderr, traceback.format_exc() 
     return 1 

def fill_api(ptr): 
    global api 
    api = ffi.cast("struct API*", ptr) 

    api.add_numbers = add_numbers 
    api.dump_buffer = dump_buffer 
    api.release_object = release_object 

संकलित:

gcc -o test_cffi test_cffi.c -I/home/jmudd/pgsql-native/Python-2.7.10.install/include/python2.7 -L/home/jmudd/pgsql-native/Python-2.7.10.install/lib -lpython2.7 
,210

निष्पादित करें:

$ test_cffi 
sum: 57.900000 
buffer: 'T\x9e\x04\x08\xa8\x93\xff\xbf]\x86\x04\x08\x00\x00\x00\x00\x00\x00\x00\x00' 
$ 
संबंधित मुद्दे