2009-09-05 20 views
11

मुझे आश्चर्य है कि क्या सामान्य लिस्प से सी ++ कोड को कॉल करने का कोई तरीका है (अधिमानतः पोर्टेबल, और यदि नहीं, अधिमानतः एसबीसीएल में, और यदि नहीं, तो क्लोजर, सीएलआईएसपी या ईसीएल)।सी कॉलिंग ++ (नहीं सी) कॉमन लिस्प से?

सी ++ को संख्यात्मक गणना के लिए अंदरूनी लूप कहा जाएगा, इसलिए कॉल तेज होने पर यह अच्छा होगा।

CFFI इस का समर्थन नहीं लगता है:

"अवधारणा अन्य भाषाओं के लिए सामान्यीकृत किया जा सकता; लेखन के समय, केवल CFFI के सी समर्थन, काफी पूरा हो गया है, लेकिन सी ++ समर्थन से किया जा रहा है इस पर काम किया।"

(मैनुअल के 4 अध्याय)

SBCL मैनुअल सी का उल्लेख नहीं करता ++ या तो; यह वास्तव में

यह अध्याय, का वर्णन सी कार्यक्रमों और पुस्तकालयों (और करने के लिए SBCL के इंटरफेस के बाद से सी इंटरफेस सामान्य भाषा यूनिक्स दुनिया के के एक प्रकार के कर रहे हैं अन्य कार्यक्रमों और सामान्य रूप में पुस्तकालयों के लिए, कहते हैं।)

सी ++ कोड ओओ और ऑपरेटर ओवरलोडिंग का उपयोग करता है, इसलिए इसे वास्तव में जी ++ के साथ संकलित करने की आवश्यकता है।

और जहां तक ​​मुझे पता है, मेरे पास सी ++ मुख्य() फ़ंक्शन और सी फ़ंक्शंस के लिए रैपर लिख सकते हैं, लेकिन दूसरी तरफ नहीं - क्या यह सच है?

वैसे भी ... वहाँ किसी तरह यह करने के लिए है?

धन्यवाद!

उत्तर

6

ओह, रुको!

ऐसा लगता है कि trick है जिसका उपयोग मैं कर सकता हूं!

मैं सी ++ में एक आवरण लिखना, आवरण कार्यों निर्वासन 'सी' की घोषणा:

#include "lib.h" 

extern "C" int lib_operate (int i, double *x) { 
... 
} 

हेडर फाइल lib.h, जो दोनों C और C++ से कहा जा सकता है, यह है:

#if __cplusplus 
extern "C" { 
#endif 

int lib_operate (int i, double *x); 

#if __cplusplus 
} 
#endif 

फिर संकलन के साथ:

g++ -c lib.cpp 
gcc -c prog.c 
gcc lib.o prog.o -lstdc++ -o prog 

एक खिलौना उदाहरण के लिए काम करने के लिए लगता है! :-)

तो, सामान्य लिस्प में मैं libstdC++ लोड करने के बाद रैपर को कॉल करूंगा।

वैसे भी, आपके उत्तरों के लिए धन्यवाद!

16

संकलन के बाद, अधिकांश सी ++ फ़ंक्शंस वास्तव में नियमित सी फ़ंक्शन कॉल तक उबालते हैं। समारोह से अधिक भार और अन्य सुविधाओं के कारण, सी ++ compilers name mangling का उपयोग इसी नाम कार्यों के बीच अंतर करना। अपने C++ कम्पाइलर के बारे में एक वस्तु डंप उपयोगिता और पर्याप्त ज्ञान को देखते हुए, आप बाहर की दुनिया से सीधे सी ++ कोड कॉल कर सकते हैं।

ऐसा कहकर कि, आपको लिस्प और आपके सी ++ कोड के बीच सी-संगत परत लिखना आसान हो सकता है। आप क्या करेंगे कि इस तरह extern "C" का उपयोग कर:

extern "C" Foo *new_Foo(int x) 
{ 
    return new Foo(x); 
} 

यह new_Foo() समारोह सी सम्मेलन बुला का पालन करें ताकि आप बाहरी स्रोतों से यह कॉल कर सकते हैं बनाता है।

+0

दूसरा विकल्प अच्छा होगा, लेकिन सी ++ कोड (जो मेरा नहीं है) ऑपरेटर ओवरलोडिंग का उपयोग करता है। मुझे लगता है कि मैं एक बाहरी "सी" ऑपरेटर + decalare नहीं कर सकता ... पहला विकल्प इस्तेमाल किए जा रहे संकलक पर निर्भर करता है, लेकिन एक अच्छा सुझाव है! – Jay

+1

आप अभी भी ओवरलोडेड ऑपरेटरों को बाहर से कॉल कर सकते हैं, आपको बस अपने एपीआई के साथ थोड़ा सा रचनात्मक होना है।उदाहरण के लिए: 'बाहरी "सी" शून्य add_Foo (फू * परिणाम, कॉन्स फू * foo1, कॉन्स फू * foo2) {* परिणाम = * foo1 + * foo2; } ' –

+3

सभी सी ++ फ़ंक्शंस" नियमित सी तक उबाल नहीं "। सदस्य फ़ंक्शंस आमतौर पर नाम मैंगलिंग के अलावा एक अलग कॉलिंग सम्मेलन का उपयोग करते हैं। (मैं x86 पर एमएसवीसी में विश्वास करता हूं, 'यह' पैरामीटर एक रजिस्टर में पारित किया जाता है, जबकि सी फ़ंक्शन में सभी पैरा स्टैक पर पास किए जाते हैं) – jalf

13

बुला सी ++ अलग नाम mangling से सी कार्यों के बजाय कार्यों में मुख्य अंतर यह है 'छुपा' इस संकेत दिए गए कि परोक्ष सदस्य कार्यों के लिए पारित कर रहे हैं की तरह सुविधाएँ हैं। सी क्रम परत इन के बारे में कुछ भी पता नहीं है, अंतर्निहित प्रकार रूपांतरण और अन्य मज़ा सी ++ सुविधाओं, इसलिए यदि आप एक सी इंटरफेस के माध्यम से C++ कॉल करने के लिए करना चाहते हैं, आप नकली इन सुविधाओं यदि आवश्यक हो सकता है।

यह मानते हुए कि आप वस्तु आप कॉल करना चाहते हैं और डेटा की आवश्यकता है यह करने के लिए कम से कम एक शून्य * धारण कर सकते हैं, तो आपको निम्न सी नीचा कर सकते हैं ++ एक सी कॉल करने के लिए कॉल

matrix->multiply(avector); 

यदि आप एक सी बनाने आवरण समारोह:

extern "C" 
void matrix_multiply(void *cpp_matrix, void *cpp_vector) { 
    reinterpret_cast<matrix_type *>(cpp_matrix)->multiply(reinterpret_cast<vector_type *>(cpp_vector); 
} 

जाहिर समारोह matrix_multiply सी ++ स्रोत कोड में बैठते हैं और इस तरह के रूप में संकलित लेकिन यह बाहर की दुनिया के लिए एक सी इंटरफ़ेस का पर्दाफाश करता होगा। जब तक आप अपारदर्शी पॉइंटर्स से बातचीत कर सकते हैं, तब तक आप उपरोक्त अनुवाद शिम के साथ ठीक हैं।

माना जाता है कि यह इस तरह की समस्या के लिए सबसे जरूरी समाधान नहीं है, लेकिन मैंने इसे अतीत में आपके जैसे परिस्थितियों में उपयोग किया है।

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

3

आपके सी ++ एबीआई के आधार पर, आपका रैपर (lib_operate उपरोक्त) किसी भी तरह से होने वाले किसी भी सी ++ अपवादों को संभालने की आवश्यकता हो सकती है। यदि आपका एबीआई टेबल-ड्राइव अपवाद हैंडलिंग करता है, तो अनचाहे अपवाद केवल (लिस्प) प्रक्रिया को क्रैश कर देंगे। यदि यह गतिशील पंजीकरण करता है, तो आप यह भी ध्यान नहीं दे सकते कि कुछ भी गलत हो गया है। किसी भी तरह से, यह बुरा है।

या, अगर आपको लपेटा कोड के लिए नो-थ्रो गारंटी मिली है, तो आप यह सब अनदेखा कर सकते हैं।

+0

मैं सहमत हूं। लेकिन इसके बारे में क्या करना है? –

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