g++
क्या हो रहा है यह देखने के लिए एक उत्पन्न बाइनरी को डिकम्पाइल करें
यह समझने के लिए कि क्यों extern
आवश्यक है, सबसे अच्छी बात यह समझना है कि उदाहरण के साथ ऑब्जेक्ट फ़ाइलों में विस्तार से क्या हो रहा है:
main.cpp
void f() {}
void g();
extern "C" {
void ef() {}
void eg();
}
/* Prevent g and eg from being optimized away. */
void h() { g(); eg(); }
जीसीसी 4.8 लिनक्स ईएलएफ आउटपुट के साथ संकलन :
g++ -c main.cpp
प्रतीक तालिका को अपघटित करें:
readelf -s main.o
आउटपुट में शामिल हैं:
Num: Value Size Type Bind Vis Ndx Name
8: 0000000000000000 6 FUNC GLOBAL DEFAULT 1 _Z1fv
9: 0000000000000006 6 FUNC GLOBAL DEFAULT 1 ef
10: 000000000000000c 16 FUNC GLOBAL DEFAULT 1 _Z1hv
11: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND _Z1gv
12: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND eg
व्याख्या
हम देखते है कि:
ef
और eg
कोड में समान नाम के साथ प्रतीकों में संग्रहीत किए गए थे
अन्य प्रतीकों मंगाई गई थीं। आइए उन्हें अनमंगल करें:
$ c++filt _Z1fv
f()
$ c++filt _Z1hv
h()
$ c++filt _Z1gv
g()
निष्कर्ष: निम्नलिखित दोनों प्रकार के प्रतीक प्रकार नहीं थे :
- परिभाषित
- घोषित लेकिन अपरिभाषित (
Ndx = UND
), लिंक पर प्रदान करने के लिए या किसी अन्य ऑब्जेक्ट फ़ाइल से समय चलाने के लिए
इसलिए आपको extern "C"
कॉल करते समय दोनों की आवश्यकता होगी :
- C ++ से C:
g++
द्वारा उत्पादित अनमैंगल्ड प्रतीकों की अपेक्षा करेंgcc
- C ++ से C: उपयोग करने के
g++
लिए अनमैन्डल प्रतीक उत्पन्न करना बताएंgcc
बाहरी सी में काम नहीं करने वाली चीजें
यह स्पष्ट हो जाता है कि किसी भी C ++ सुविधा के लिए जिसे नाम की आवश्यकता है, अंदर काम नहीं करेगी extern C
:
extern "C" {
// Overloading.
// error: declaration of C function ‘void f(int)’ conflicts with
void f();
void f(int i);
// Templates.
// error: template with C linkage
template <class C> void f(C i) { }
}
C ++ उदाहरण से न्यूनतम रनवेबल C
पूर्णता के लिए और वहाँ से बाहर के newbs के लिए, यह भी देखें: C ++ प्रोजेक्ट में C स्रोत फ़ाइलों का उपयोग कैसे करें?
C ++ से C को कॉल करना बहुत आसान है: प्रत्येक C फ़ंक्शन में केवल एक संभव गैर-मैनगल्ड प्रतीक है, इसलिए किसी अतिरिक्त कार्य की आवश्यकता नहीं है।
main.cpp
#include <cassert>
#include "c.h"
int main() {
assert(f() == 1);
}
ch
#ifndef C_H
#define C_H
/* This ifdef allows the header to be used from both C and C++. */
#ifdef __cplusplus
extern "C" {
#endif
int f();
#ifdef __cplusplus
}
#endif
#endif
सीसी
#include "c.h"
int f(void) { return 1; }
Daud:
g++ -c -o main.o -std=c++98 main.cpp
gcc -c -o c.o -std=c89 c.c
g++ -o main.out main.o c.o
./main.out
extern "C"
लिंक के बिना के साथ विफल रहता है:
main.cpp:6: undefined reference to `f()'
क्योंकि g++
एक पके हुए आम को खोजने की उम्मीद है f
, जो gcc
उत्पन्न नहीं हुआ।
GitHub पर उदाहरण ।
C उदाहरण से न्यूनतम रनर C ++
C ++ से कॉल करना थोड़ा कठिन है: हमें मैन्युअल रूप से प्रत्येक फ़ंक्शन के गैर-मैंगल्ड संस्करण बनाने होंगे जिन्हें हम उजागर करना चाहते हैं।
यहाँ हम बताते हैं कि C ++ फंक्शन ओवरलोड को C में कैसे एक्सपोज़ किया जाए।
main.c
#include <assert.h>
#include "cpp.h"
int main(void) {
assert(f_int(1) == 2);
assert(f_float(1.0) == 3);
return 0;
}
cpp.h
#ifndef CPP_H
#define CPP_H
#ifdef __cplusplus
// C cannot see these overloaded prototypes, or else it would get confused.
int f(int i);
int f(float i);
extern "C" {
#endif
int f_int(int i);
int f_float(float i);
#ifdef __cplusplus
}
#endif
#endif
cpp.cpp
#include "cpp.h"
int f(int i) {
return i + 1;
}
int f(float i) {
return i + 2;
}
int f_int(int i) {
return f(i);
}
int f_float(float i) {
return f(i);
}
Daud:
gcc -c -o main.o -std=c89 -Wextra main.c
g++ -c -o cpp.o -std=c++98 cpp.cpp
g++ -o main.out main.o cpp.o
./main.out
इसके बिना extern "C"
विफल रहता है:
main.c:6: undefined reference to `f_int'
main.c:7: undefined reference to `f_float'
क्योंकि g++
उत्पन्न प्रतीक जो gcc
नहीं मिल सकते हैं।
GitHub पर उदाहरण ।
उबंटू 18.04 में परीक्षण किया गया।