2012-07-28 19 views
5

का उपयोग कर सी से पायथन फ़ंक्शन को कॉल करते हुए मेरे पास निम्न प्रश्न है। हमें सी कोड में कॉलबैक फ़ंक्शन पास करना होगा। समारोह में एक ही मॉड्यूल में एक Cython समारोह है, तो स्थिति काफी सरलपायथन/साइथन/सी और कॉलबैक, सीथॉन

है Cython में:

def callme(int x): 
    c_callme(x, <int (*)(int)>&callbackme) 

cdef int callbackme(int x): 
    print <int> x 
    return <int>x 

सी में:

int c_callme(int x, int (*f)(int)) 
{ 
    printf("---%d\n",x); 
    printf("--%d\n",f(x)); 
    return x; 
} 

सवाल है इस प्रकार है: हम चाहते हैं इस कोड को सबसे पाइथोनिक तरीके से सामान्यीकृत करें ताकि यह कॉलबैक तर्कों के रूप में भी अजगर कार्यों को स्वीकार कर सके (बेशक, कुछ अतिरिक्त परत की आवश्यकता है), और सी/साइथन अन्य मॉड्यूल से भी कार्य करता है। मुझे लगता है कि, एक अलग मॉड्यूल से सी/साइथन कार्यों के लिए किसी को इन कार्यों का पता प्राप्त करना होगा (लंबे int में परिवर्तित करें?) और पायथन फ़ंक्शन के लिए एक निश्चित रैपर की आवश्यकता होती है

+0

के माध्यम से, अपने अजगर कार्य करने के लिए तर्क पारित करने के लिए कृपया कोड स्वरूपण ... – ThiefMaster

उत्तर

0

मुझे लगता है कि सबसे आसान तरीका लपेटना होगा सी

cdef class Callback(object): 
    cdef int (*f)(int)  # I hope I got the syntax right... 

    def __call__(int x): 
     return self.f(x) 

में कॉलबैक ताकि आप समारोह है कि कॉलबैक कॉल करना होगा करने के लिए, इस प्रकार की वस्तुओं, साथ ही किसी भी अन्य प्रतिदेय पारित कर सकते हैं।

हालांकि, अगर आपको सी से कॉलबैक कॉल करना होगा, तो आपको इसे एक अतिरिक्त तर्क, अर्थात् पाइथन ऑब्जेक्ट का वैकल्पिक पता, शायद 'शून्य * पर डाला जाना चाहिए।

(कृपया long को नहीं डाली समारोह संकेत करते हैं, या आप अपरिभाषित व्यवहार हो सकता है। मैं नहीं यकीन है कि अगर आप सुरक्षित रूप से कुछ भी करने के लिए एक समारोह सूचक डाल सकता भी void* हूँ,।)

+0

मैं भी उस दिशा में सोच रहा था के बारे में FAQ पढ़ें दिखाया गया है। लेकिन कोड बिल्कुल संकलित नहीं होता है :(। क्या आप अधिक विस्तार कर सकते हैं कि हमें फ़ंक्शन पॉइंटर्स को लंबे समय तक क्यों डालना नहीं है? –

+0

@IvanOseledets: फ़ंक्शन पॉइंटर मानों को 'long' में फिट करने की गारंटी नहीं है, और इसके विपरीत। एक मशीन पर काम कर सकता है, लेकिन दूसरे पर असफल हो सकता है। यह कोड संकलित नहीं करता है शायद सिंटैक्स त्रुटि के कारण, मेरे पास साइथन इंस्टॉलेशन आसान नहीं है। –

9

इस उदाहरण में , extracted from a Python wrapperCubature integration C library पर, एक पायथन फ़ंक्शन को सी फ़ंक्शन में पास किया जाता है जिसमें प्रोटोटाइप cfunction द्वारा दिया गया है। आप एक ही प्रोटोटाइप के साथ एक समारोह, cfunction_cb (कॉलबैक) कहा जाता है बना सकते हैं, और इस उदाहरण में एक ही प्रकार, int) लौटने:

cdef object f 
ctypedef int (*cfunction) (double a, double b, double c, void *args) 

cdef int cfunction_cb(double a, double b, double c, void *args): 
    global f 
    result_from_function = (<object>f)(a, b, c, *<tuple>args) 
    for k in range(fdim): 
     fval[k] = fval_buffer[k] 
    return 0 

जब सी फ़ंक्शन कॉल, आप सी का उपयोग कर अपने कॉलबैक आवरण डाल सकता प्रोटोटाइप:

def main(pythonf, double a, double b, double c, args): 
    global f 
    f = pythonf 
    c_function(<cfunction> cfunction_cb, 
       double a, 
       double b, 
       double c, 
       <void *> args) 

इस उदाहरण में यह भी कैसे सी

+1

इसे उत्तर के रूप में स्वीकार किया जाना चाहिए, यह ठीक काम करता है। वैश्विक उदाहरण उदाहरण को जीवित और अच्छी तरह से रखता है। – dashesy

संबंधित मुद्दे