c++ 的链接指示器 extern "C"
1. c++ 使用c的函数
c++ 标准库使用 c标准库,比如
cstdio /** @file include/cstdio * This is a Standard C++ Library file. You should @c #include this file * in your programs, rather than any of the "*.h" implementation files. * * This is the C++ version of the Standard C Library header @c stdio.h, * and its contents are (mostly) the same as that header, but are all * contained in the namespace @c std (except for names which are defined * as macros in C). */ extern "C" int (snprintf)(char * restrict, size_t, const char * restrict, ...);
再来一个简单例子
-- math.h
#ifndef __MATH_H__ #define __MATH_H__ #ifdef __cplusplus extern "C" { #endif int func(int,int); #ifdef __cplusplus } #endif #endif
-- math.c
#include "math.h" int func(int a,int b) { return a+b; }
-- 编译成静态库:
-- gcc -c math.c
-- ar -r librmath.a *.o
-- math.cpp
#include "math.h" #include <iostream> using namespace std; int main() { int a= 2,b = 3; int c = func(a,b); // 直接调用c接口 cout << c << endl; }
-- 编译成可执行程序:
-- g++ math.cpp -L./ -lrmath
-- ./a.out
如果没有加上extern "C",则编译时报链接错误:
math.cpp:(.text+0x21): undefined reference to `func(int, int)'
collect2: ld returned 1 exit status
2. 导出c++函数到c语言
-- math.h
class sample { public: int func(int a, int b); };
-- math.cpp
#include "math.h" int sample::func(int a, int b) { return a + b; }
-- g++ -fpic -shared -g -o librmath.so math.cpp -I ./
写c代码包装一下
-- mymath.h
#ifdef __cplusplus extern "C" { #endif int myfunc(int, int); #ifdef __cplusplus } #endif
-- mymath.c
#include "mymath.h" #include "math.h" int myfunc(int a, int b) { sample s; return s.func(a, b); }
-- g++ -fpic -shared -g -o libmymath.so mymath.cpp -lrmath -I ./ -L ./
测试一下:
-- main.c
#include <stdio.h> #include "mymath.h" int main() { printf("%d\n", myfunc(1, 2)); return 0; }
-- gcc main.c -L./ -I ./ -lrmath -lmymath -Wl,-rpath=./
-- ./a.out
如果想要编译成静态库:
g++ -c math.cpp
ar -r librmath.a math.o
g++ -c mymath.cpp
ar -r libmymath.a mymath.o
gcc main.c libmymath.a librmath.a -lstdc++
注意两点
1. -lstdc++
undefined reference to `__gxx_personality_v0'
因为:
Note that programs using C++ object files must always be linked with g++, in order to supply the appropriate C++ libraries. Attempting to link a C++ object file with the C compiler gcc will cause "undefined reference" errors for C++ standard library functions
C++ source files conventionally use one of the suffixes .C, .cc, .cpp, .CPP, .c++, .cp, or .cxx; C++ header files often use .hh, .hpp, .H, or (for shared template code) .tcc; and preprocessed C++ files use the suffix .ii. GCC recognizes files with these names and compiles them as C++ programs even if you call the compiler the same way as for compiling C programs (usually with the name gcc).
大概意思是gcc根据后缀名去链接标准库,上面例子gcc没有检测到c++,所以默认不去链接c++基础库。
2. main.c libmymath.a librmath.a 这三个的顺序不能动,因为:
When the GNU linker sees a library, it discards all symbols that it doesn't need. In this case, your library appears before your .cpp file, so the library is being discarded before the .cpp file is compiled.
所以推荐动态库的方式。