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. 

所以推荐动态库的方式。

猜你喜欢

转载自www.cnblogs.com/tenyearboyue/p/12037824.html