extern "C"总结

参考文章:
http://blog.csdn.net/caspiansea/article/details/9676153
https://www.cnblogs.com/eyeszjwang/articles/2839175.html

在c++文件中声明一个非C++函数中的extern “C”的作用(C++调用c函数)是让C++链接器在找调用函数的符号时采用c的方式

导出C++函数到其他语言中(c语言调用c++)extern “C”的作用是告诉编译器依照C的方式来编译封装接口,但接口函数里面的C++语法还是按C++方式编译

一、C++中调用C的代码,具体方式有以下几种:
1.moduleA.h:

#ifndef MODULE_A_H
#define MODULE_A_H
int foo(int i);
#endif

moduleA.c:

#include<stdio.h>
#include"moduleA.h"
int foo(int i)
{
    printf("I love you !");
    return 0;
}

moduleB.cpp:

#include<stdio.h>

extern "C" {
    #include"moduleA.h"
}
int main()
{
    foo(1);
    return 0;
}

makefile:

xrb:moduleA.o moduleB.o
    g++ -o xrb.exe moduleA.o moduleB.o
    @echo "makefile"
moduleA.o:moduleA.c
    gcc -c moduleA.c

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

.PHONY: clean
clean:
    rm xrb.exe moduleA.o moduleB.o
    @echo "makefile"

运行结果:
这里写图片描述
2.extern “C”可以用在.cpp文件中,也可以用在.c文件中,也能用在c语言头文件(.h文件)中,用在.c和c语言头文件中会不会报错,关键是使用gcc还是g++编译,gcc编译会报错,g++编译不会报错:
(1)extern “C”在c语言头文件中,用gcc编译报错,用g++编译可以通过
moduleA.h:

#ifndef MODULE_A_H
#define MODULE_A_H
extern "C" int foo();
#endif

moduleA.c:

#include<stdio.h>
#include"moduleA.h"
int foo(void)
{
    printf("I love you !");
    return 0;
}

moduleB.cpp:

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

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

makefile:

xrb:moduleA.o moduleB.o
    g++ -o xrb.exe moduleA.o moduleB.o
    @echo "makefile"
moduleA.o:moduleA.c
    gcc -c moduleA.c

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

.PHONY: clean
clean:
    rm xrb.exe moduleA.o moduleB.o
    @echo "makefile"

运行结果:
这里写图片描述

(2)extern “C”在.c中,用g++编译不会报错,成功:
module.c:

#include<stdio.h>
//#include"moduleA.h"
extern "C" int main(void)
{
    printf("I love you !");
    return 0;
}

执行g++ module.c即可

3.网上说的第三种方法也是错的。

/*C语言头文件:CDemo.h */  
#ifndef C_SRC_DEMO_H  
#define C_SRC_DEMO_H  
extern int Function(int x,int y);  
#endif  // C_SRC_DEMO_H  

/* C语言实现文件:CDemo.c */  
#include "CDemo.h"  
int Function ( int x, int y )  
{  
  ... // processing code  
}  

// C++调用文件  
#include "CDemo.h"  
extern "C" int Function(int x,int y);  

int main()  
{  
     Function (2,3);  
     return 0;  
} 

二、C中调用C++代码
1.代码:
moduleA.h:

#ifndef MODULE_A_H
#define MODULE_A_H
extern "C" int foo(int i);
#endif

module.cpp:

#include<iostream>
#include"moduleA.h"
using std::cout;
using std::endl;
int foo(int i)
{
    cout<<"I love you !"<<endl;
    return 0;
}

moduleB.c:

#include<stdio.h>
extern int foo(int i);

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

makefile:

xrb:module.o moduleB.o
    g++ -o xrb.exe module.o moduleB.o
    @echo "makefile"
module.o:module.cpp
    g++ -c module.cpp

moduleB.o:moduleB.c
    gcc -c moduleB.c

.PHONY: clean
clean:
    rm xrb.exe module.o moduleB.o
    @echo "makefile"

运行结果:
这里写图片描述

这个例子可见,导出C++函数到其他语言中(c语言调用c++)extern “C”的作用是告诉编译器依照C的方式来编译封装接口,但接口函数里面的C++语法还是按C++方式编译。
2.代码:
moduleA.h:

#ifndef MODULE_A_H
#define MODULE_A_H

#ifdef __cplusplus
extern "C" {
#endif
  int foo(int i);
#ifdef __cplusplus
}
#endif

#endif

module.cpp:

#include<iostream>
#include"moduleA.h"
using std::cout;
using std::endl;
int foo(int i)
{
    cout<<"I love you !"<<endl;
    return 0;
}

moduleB.c:

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

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

makefile:

xrb:module.o moduleB.o
    g++ -o xrb.exe module.o moduleB.o
    @echo "makefile"
module.o:module.cpp
    g++ -c module.cpp

moduleB.o:moduleB.c
    gcc -c moduleB.c

.PHONY: clean
clean:
    rm xrb.exe module.o moduleB.o
    @echo "makefile"

运行结果:
这里写图片描述

3.用C语言调用C++的类
1.代码:
moduleA.h:

#ifndef MODULE_A_H
#define MODULE_A_H
class Apple
{
public:
  Apple();
  int send(void);
private:
  int i;
};
#endif

module.cpp:

#include<iostream>
#include"moduleA.h"
using std::cout;
using std::endl;
Apple::Apple():i(10)
{

}

int Apple::send(void)
{
    cout<<"I love you !"<<"  "<<i<<endl;
    return 0;
}

moduleB.h:

#ifndef MODULE_B_H
#define MODULE_B_H
struct tagApple;
#ifdef __cplusplus
extern "C" {
#endif
  struct tagApple *GetInstance(void);
  int tagsend(struct tagApple *pApple);
#ifdef __cplusplus
}
#endif

#endif

这里使用了#ifdef __cplusplus,这样在test.c包含moduleB.h并用gcc编译test.c的时候不会因为extern “C”报错

moduleB.cpp:

#include"moduleB.h"
#include"moduleA.h"
struct tagApple{
    Apple apple;
};
struct tagApple *GetInstance(void)
{
    return new struct tagApple;
}
int tagsend(struct tagApple *pApple)
{
    return pApple->apple.send();
}

test.c:

#include "moduleB.h"
#include<stdio.h>
extern struct tagApple *GetInstance(void);
extern int tagsend(struct tagApple *pApple);

int main(void)
{
  struct tagApple *pApple;
  pApple=GetInstance();
  tagsend(pApple);
  printf("Yes~");
  return 0;
}

makefile:

#下面这个编译不知道为什么一定要把-lmodule加上,我觉得只加上-lmoduleB就够了(其实我也不懂。。)。
#2018.1.10补充:参看http://blog.csdn.net/cjsycyl/article/details/46864341这篇文章可以更新下面的#makefile#以及解释为什么要加上-lmoduleB
xrb:libmoduleB.so test.c
    gcc test.c -L. -lmoduleB -lmodule -o xrb.exe
    @echo "makefile"


libmoduleB.so:moduleB.cpp libmodule.so
    g++ -o libmoduleB.so -fpic -shared moduleB.cpp -L. -lmodule
libmodule.so:module.cpp
    g++ -o libmodule.so -fpic -shared module.cpp



.PHONY: clean
clean:
    rm xrb.exe libmodule.so libmoduleB.so
    @echo "makefile"

这样就可以编译成功了,不过在运行前,要在命令行输入

export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH

上面的makefile在ubuntu中可以运行成功,在windows会报错

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值