C ++ कोड से C फ़ंक्शन को कॉल करें


90

मेरे पास एक सी फ़ंक्शन है जिसे मैं C ++ से कॉल करना चाहूंगा। मैं " extern "C" void foo()" तरह के दृष्टिकोण का उपयोग नहीं कर सका क्योंकि जी फ़ंक्शन जी ++ का उपयोग करके संकलित करने में विफल रहा। लेकिन यह जीसीसी का उपयोग कर ठीक संकलन करता है। किसी भी विचार कैसे C ++ से फ़ंक्शन को कॉल करना है?


1
क्या आप कृपया कुछ उदाहरण कोड और g++त्रुटि संदेश लिख सकते हैं
Matthieu Rouget

7
यदि आप इसे C ++ कंपाइलर के साथ संकलित करते हैं, तो यह C ++ है। C कोड को C ++ कंपाइलर के साथ संकलित करने की आवश्यकता नहीं है। वे अलग-अलग भाषाएं हैं। आपका कोड मान्य नहीं है C ++ और उसके बाद C ++ कंपाइलर के साथ संकलन नहीं है।
xaxxon

3
@ मैथ्यू रीरौटvoid valid_in_C_but_not_in_CPlusPlus(size_t size) { char variable_length_array[size]; }
ऑटिस्टिक

2
मेरी कोशिश: void f(void *pv) { int *pi = pv; *pi = 42; }^^
gx_

1
इसे खुला छोड़ दिया जाना चाहिए, विशेष रूप से क्योंकि इसमें अच्छे उत्तर हैं जो बताते हैं कि C (C ++ के बजाय) संकलक का उपयोग C कोड के लिए कैसे किया जा सकता है।
क्रिस स्ट्रैटन

जवाबों:


126

इस तरह सी कोड संकलित करें:

gcc -c -o somecode.o somecode.c

फिर इस तरह सी + + कोड:

g++ -c -o othercode.o othercode.cpp

फिर उन्हें सी + + लिंकर के साथ एक साथ लिंक करें:

g++ -o yourprogram somecode.o othercode.o

आपको C ++ कंपाइलर को यह भी बताना होगा कि C फ़ंक्शन के लिए घोषणा को शामिल करते समय C हेडर आ रहा है। तो इसके othercode.cppसाथ शुरू होता है:

extern "C" {
#include "somecode.h"
}

somecode.h कुछ ऐसा होना चाहिए:

 #ifndef SOMECODE_H_
 #define SOMECODE_H_

 void foo();

 #endif


(मैंने इस उदाहरण में gcc का उपयोग किया है, लेकिन सिद्धांत किसी भी संकलक के लिए समान है। क्रमशः C और C ++ के रूप में अलग-अलग बनाएँ, फिर इसे एक साथ लिंक करें।)


7
@ अच्छा अंक। कुछ लोग extern "C"हेडर के साथ रैप करके अपने C में कुछ C ++ को घटाते हैं #ifdef __cplusplus
खोलना

@Arne नीचे मेरा जवाब देखें। खोलना जैसा कि आप देख सकते हैं कि मैं उनमें से एक हूँ;)
gx_

1
आपको बहुत - बहुत धन्यवाद ! यह मेरे लिए बहुत उपयोगी था :)
हेशम एराकी

मुझे निम्न त्रुटि प्राप्त हो रही थी: त्रुटि: # 337: लिंकेज विनिर्देश पिछले "फू" (पंक्ति 1 पर घोषित) के साथ असंगत है। अब इसका संकलन ठीक है। क्या कोई समझा सकता है?
FaizanHussainRabbani

@FaizanRabbani, बहुत अधिक विस्तार के बिना नहीं।
प्रो। फल्केन

61

मुझे अन्य उत्तर और टिप्पणियों से बिट्स और टुकड़ों को इकट्ठा करने दें, ताकि आप साफ-सुथरे सी और सी ++ कोड के साथ एक उदाहरण दे सकें:

सी हिस्सा:

foo.h :

#ifndef FOO_H
#define FOO_H

void foo(void);

#endif 

foo.c

#include "foo.h"

void foo(void)
{
    /* ... */
}

इसके साथ संकलित करें gcc -c -o foo.o foo.c

सी ++ भाग:

bar.cpp

extern "C" {
  #include "foo.h" //a C header, so wrap it in extern "C" 
}

void bar() {
  foo();
}

इसके साथ संकलित करें g++ -c -o bar.o bar.cpp

और फिर सभी को एक साथ लिंक करें:

g++ -o myfoobar foo.o bar.o

Rationale: C कोड सादा C कोड होना चाहिए, #ifdef"किसी दिन शायद मैं इसे किसी अन्य भाषा से कॉल करूंगा" के लिए नहीं। यदि कुछ C ++ प्रोग्रामर आपके C फ़ंक्शन को कॉल करते हैं, तो यह उनकी समस्या है कि ऐसा कैसे करें, आपका नहीं। और यदि आप C ++ प्रोग्रामर हैं, तो C हैडर आपका नहीं हो सकता है और आपको इसे बदलना नहीं चाहिए, इसलिए अनमैन्डल फंक्शन नामों (यानी extern "C") का हैंडलिंग आपके C ++ कोड में आता है।

आप निश्चित रूप से, अपने आप को एक सुविधा C ++ हेडर लिख सकते हैं जो सी हेडर को extern "C"घोषणा में लपेटने के अलावा कुछ नहीं करता है ।


7
वैध लगता है।
राशन के

अंत में इस की पूरी तरह से स्पष्ट व्याख्या। अनेक अनेक धन्यवाद!
बजे डैनियल सूटर

16

मैं प्रो। फालकेन के उत्तर से सहमत हूं , लेकिन अर्ने मर्ट्ज़ की टिप्पणी के बाद मैं एक संपूर्ण उदाहरण देना चाहता हूं (सबसे महत्वपूर्ण हिस्सा यह है #ifdef __cplusplus):

somecode.h

#ifndef H_SOMECODE
#define H_SOMECODE

#ifdef __cplusplus
extern "C" {
#endif

void foo(void);

#ifdef __cplusplus
}
#endif

#endif /* H_SOMECODE */

somecode.c

#include "somecode.h"

void foo(void)
{
    /* ... */
}

othercode.hpp

#ifndef HPP_OTHERCODE
#define HPP_OTHERCODE

void bar();

#endif /* HPP_OTHERCODE */

othercode.cpp

#include "othercode.hpp"
#include "somecode.h"

void bar()
{
    foo(); // call C function
    // ...
}

फिर आप प्रो। फालकेन के निर्देशों का संकलन और लिंक करने के लिए अनुसरण करते हैं।

यह काम करता है क्योंकि जब संकलन किया जाता है gcc, तो मैक्रो __cplusplusपरिभाषित नहीं होता है, इसलिए somecode.hइसमें शामिल हेडर somecode.cप्रीप्रोसेसिंग के बाद इस तरह होता है:

void foo(void);

और जब संकलित किया जाता है g++, तब परिभाषित किया __cplusplus जाता है, और इसलिए इसमें शामिल हेडर othercode.cppअब इस तरह है:

extern "C" {

void foo(void);

}

4
thb, मुझे #ifdef __cplusplusC कोड पसंद नहीं है। C कोड निम्न स्तर है, और इसे किसी दिन C ++ कोड से कॉल करने पर परेशान नहीं होना चाहिए। Imo कि #ifdefइसका उपयोग केवल C ++ कोड में है यदि आप C ++ में लिखी गई लाइब्रेरी के लिए C बाइंडिंग हेडर प्रदान करना चाहते हैं, अन्य तरीके से नहीं।
अर्ने मर्ट्ज़

2
@ Prof.Falken बेशक, लेकिन यह एक परिभाषित है जो C ++ कोड की "डाउनवर्ड" कंपैटिबिलिटी प्रदान करने में सक्षम है, सी कोड के लिए नहीं।
आर्ने मर्ट्ज़

1

यह उत्तर एक ऐसे मामले से प्रेरित है जहां अर्ने का तर्क सही था। एक विक्रेता ने एक पुस्तकालय लिखा जो एक बार सी और सी ++ दोनों का समर्थन करता था; हालांकि, नवीनतम संस्करण ने केवल सी का समर्थन किया। कोड में छोड़ी गई निम्नलिखित शाब्दिक निर्देश भ्रामक थे:

#ifdef __cplusplus
extern "C" {
#endif

इसने मुझे C ++ में संकलन करने की कोशिश में कई घंटे लगाये। बस C ++ से C को कॉल करना बहुत आसान था।

Ifdef __cplusplus सम्मेलन एकल जिम्मेदारी सिद्धांत का उल्लंघन है। इस सम्मेलन का उपयोग करने वाला एक कोड दो चीजों को एक साथ करने की कोशिश कर रहा है:

  • (1) C और - में एक फ़ंक्शन निष्पादित करें
  • (2) C ++ में समान फ़ंक्शन को निष्पादित करते हैं

यह एक ही समय में अमेरिकी और ब्रिटिश दोनों अंग्रेजी में लिखने की कोशिश कर रहा है। यह अनावश्यक रूप से #ifdef __thequeensenglish स्पैनर #elif __yankeeenglish रिंच # व्यर्थ # उपकरण को फेंक रहा है जो कोड में #endif को पढ़ने के लिए कोड को कठिन बनाता है।

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

यह उबंटू लिनक्स पर संकलित करने के लिए मैंने आर्ने के कोड में किए गए संशोधनों का एक रिकॉर्ड है।

foo.h :

#ifndef FOO_H
#define FOO_H

void foo(void);

#endif 

foo.c

#include "foo.h"
#include <stdio.h>

void foo(void)
{
     // modified to verify the code was called
     printf("This Hello World was called in C++ and written in C\n");
}

bar.cpp

extern "C" {
    #include "foo.h" //a C header, so wrap it in extern "C" 
}

int main() {
  foo();
  return(0);
}

makefile

# -*- MakeFile -*-
# dont forget to use tabs, not spaces for indents
# to use simple copy this file in the same directory and type 'make'

myfoobar: bar.o foo.o
    g++ -o myfoobar foo.o bar.o 

bar.o: bar.cpp
    g++ -c -o bar.o bar.cpp

foo.o: foo.c
    gcc -c -o foo.o foo.c
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.