在线笔记
全部博文(596)
分类: C/C++
2013-03-15 23:06:01
一、 基础知识
函数调用,编译器只要知道函数的参数类型和返回值以及函数名就可以进行编译连接。那么为了让C调用C++接口或者
是说C++调用C接口,就必须是调用者和被调用者有着同样的编译方式。这既是extern "C"的作用,
extern “C”是的程序按照C的方式编译。
//cplus.cpp
//按照C++方式编译程序
int Operation(int){}
$g++ -c cplus.cpp -o cplus.o
$nm cplus.o
00000000 T _Z9Operationi
//C++
extern "C"
int Operation(int) {}
$g++ -c cplus.cpp -o cplus.o
$nm cplus.o
00000000 T Operation
提供给C的接口必须加 extern "C"。这里还只是确定了编译方式,extern "C"只能让编译器安C的方式编译。但是C并不认识
extern "C",这里还要加一道工序:
在C文件中 extern下接口。
extern int Operation(int)
这样C程序就认识接口函数了。下面以一个简单的例子来说明具体如何让封装C++接口给C使用。
$ gcc -o cpp2c cpp2c.o csayhello.o -lstdc++ (gcc,链接的时候要指定 C++ 标准库)
$ g++ -o cpp2c cpp2c.o csayhello.o (g++,C++ 标准库默认会被链接。)
或者
$ gcc cpp2c.cpp csayhello.c -lstdc++
1.先看代码
//add.c,还是正常的C代码,没有一丝不同
#include
int add(int m, int n)
{
return m + n;
}
void _cout(int m)
{
printf("result = %d\n", m);
}
$ gcc -c add.c
$ nm add.o
0000000e T _cout
00000000 T add
U printf
可以看出
int add(int m, int n); ==> U add
void _cout(int m); ==> U _cout
2.再看代码
//main.cpp
#include
//没有加extern "C"
int add(int m, int n);
void _cout(int m);
int main(int argc, char **argv)
{
_cout(add(1,1));
return 0;
}
$ g++ -c main.cpp
$ nm main.o
0000000e T _cout
00000000 T add
U printf
0000006c t _GLOBAL__I_main
U _Z3addii
0000002c t _Z41__static_initialization_and_destruction_0ii
U _Z5_couti
U _ZNSt8ios_base4InitC1Ev
U _ZNSt8ios_base4InitD1Ev
00000000 b _ZStL8__ioinit
U __cxa_atexit
U __dso_handle
U __gxx_personality_v0
00000000 T main
可以看出
int add(int m, int n); ==> U _Z3addii
void _cout(int m); ==> U _Z5_couti
3.加了extern "C",再看代码
#include
extern "C" {
int add(int m, int n);
void _cout(int m);
};
int main(int argc, char **argv)
{
_cout(add(1,1));
return 0;
}
$ g++ -c main.cpp
$ nm main.o
0000006c t _GLOBAL__I_main
0000002c t _Z41__static_initialization_and_destruction_0ii
U _ZNSt8ios_base4InitC1Ev
U _ZNSt8ios_base4InitD1Ev
00000000 b _ZStL8__ioinit
U __cxa_atexit
U __dso_handle
U __gxx_personality_v0
U _cout
U add
00000000 T main
可以看出,加extern "C"
int add(int m, int n); ==> U add
void _cout(int m); ==> U add
4.关键来了!!!
对比,没有加extern "C"
int add(int m, int n); ==> U _Z3addii
void _cout(int m); ==> U _Z5_couti
可以得出结论,extern "C"能让G++编译器按C的方式编译。
5.更好的方法是建一个add.h的头文件,里面包含要引用的C函数,完整代码
//add.h
#ifndef ADD_H_
#define ADD_H_
extern "C" {
int add(int m, int n);
void _cout(int m);
};
#endif
//add.c
#include
int add(int m, int n)
{
return m + n;
}
void _cout(int m)
{
printf("result = %d\n", m);
}
//main.cpp
#include
#include "add.h"
int main(int argc, char **argv)
{
_cout(add(1,1));
return 0;
}
6.不小心用GCC编译了add.h,问题来了
$ gcc add.c add.h
add.h:4: error: expected identifier or ‘(’ before string constant
额,extern "C" 是C++发明的,只有G++可以编译,GCC就不能编译了。。
没事,找个方法让GCC编译时,没有extern "C",话说G++编译是有一个默认的宏__cplusplus。看清楚,不是__cpluscplus
说到这,你懂?
不懂看代码
//add.h,带了个套的C函数声明
#ifndef ADD_H_
#define ADD_H_
#ifdef __cplusplus
extern "C" {
#endif
int add(int m, int n);
void _cout(int m);
#ifdef __cplusplus
};
#endif
#endif
//add.c,还是正常的C代码,没有一丝不同
#include
int add(int m, int n)
{
return m + n;
}
void _cout(int m)
{
printf("result = %d\n", m);
}
//main.cpp,引用了带了套的C函数声明
#include
#include "add.h"
int main(int argc, char **argv)
{
_cout(add(1,1));
return 0;
}
7.C++调用C结束。