C和C++文件混合编译

一个项目中若同时存在.c文件和.cpp文件,该如何编译呢?

首先,来看一下编译的一些小知识:

1.gcc编译*.c/*.cpp文件依据各自的文件类型各自编译为C型目标文件和C++型目标文件

2.g++编译*.c/*.cpp文件,都是编译为C++类型的目标文件

3.在第2点基础上,使用g++时,不论是*.c还是*.cpp都将链接std c++库。而gcc是一句各自文件类型链接相应的std c库或者是std c++库

4.gcc编译*.c之后预定义的宏比较少

5.gcc编译*.cpp文件或者g++编译之后,预定义的宏比较多。

定义如下文件:

hw.c  hw.h  main.cpp  test.cpp  test.h

main模块调用test模块,test模块调用hw模块

首先,列出各个文件最初始的内容:

hw.h

#ifndef HW_H
#define HW_H

int get_hw();

#endif
hw.c

#ifndef HW_H
#	include "hw.h"
#endif


int get_hw()
{
	return 100;
}
test.h

#ifndef TEST_H
#define TEST_H

void do_test();

#endif
test.cpp

#ifndef TEST_H
#	include "test.h"
#endif

#ifndef HW_H
#	include "hw.h"
#endif
#include <stdio.h>
void do_test()
{
	printf("hw: %d\n", get_hw());
}
main.cpp

#ifndef TEST_H
#	include "test.h"
#endif


int main(int argc, char** argv)
{
	do_test();
	return 0;
}

一.用g++编译

Makefile

myexpect : main.o hw.o test.o
	g++ -o myexpect main.o hw.o test.o

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

hw.o : hw.c
	g++ -c hw.c

test.o : test.cpp
	g++ -c test.cpp
在键入make后可以成功生成myexpect程序。这体现了文章开头的小知识1。使用nm 命令查看hw.o中的符号

root@hu-virtual-machine:/home/hu/project/c_# nm hw.o 
0000000000000000 T _Z6get_hwv
可以看到get_hw符号前,后都加了一些东西,先记在这儿,和下文做对比

二.hw.h中的符号由extern "C"保护

将hw.h中的内容改变为下文

#ifndef HW_H
#define HW_H

#ifdef __cplusplus
extern "C"{
#endif

	int get_hw();

#ifdef __cplusplus
}
#endif

#endif
沿用上面的Makefile,执行make后,也能正常生成myexpect程序。这时,使用nm工具,观察hw.o

root@hu-virtual-machine:/home/hu/project/c_# nm hw.o 
0000000000000000 T get_hw
多么的明了,多么的干净,显然,get_hw没有经过修改,所以,hw.o就是C型目标文件。和上面的比较起来,一中的hw.o就是C++型目标文件

三.test.cpp中的#include "hw.h" 由extern “C” 保护

现在,移除调二中的对hw.h的修改,恢复为原始的没有extern "C"的内容。将test.cpp改变为如下

#ifndef TEST_H
#	include "test.h"
#endif

#ifndef HW_Hi
extern "C" {
#	include "hw.h"
}
#endif
#include <stdio.h>
void do_test()
{
	printf("hw: %d\n", get_hw());
}
依然沿用上面的Makefile,执行make后输出

g++ -c main.cpp
g++ -c hw.c
g++ -c test.cpp
g++ -o myexpect main.o hw.o test.o
test.o: In function `do_test()':
test.cpp:(.text+0x5): undefined reference to `get_hw'
collect2: error: ld returned 1 exit status
make: *** [myexpect] Error 1
这是因为在test.cpp中的extern "C" { #include "hw.h" } 表示的意思为:test.cpp期望一个C型hw.o的目标文件,然而在Makefile中使用了g++去编译hw.c生成了C++型目标文件,这就导致了问题产生。针对Makefile做如下修改

myexpect : main.o hw.o test.o
	g++ -o myexpect main.o hw.o test.o

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

hw.o : hw.c
	gcc -c hw.c

test.o : test.cpp
	g++ -c test.cpp
执行make后可以正常生成myexpect程序。这是因为使用gcc去编译*.c文件,肯定会生成C型目标文件

四.所有模块由gcc编译,链接时使用g++进行链接

将所有文件内容恢复到原始状态

先看一下所有模块由gcc编译,再由gcc进行链接

myexpect : main.o hw.o test.o
	gcc -o myexpect main.o hw.o test.o

main.o : main.cpp
	gcc -c main.cpp

hw.o : hw.c
	gcc -c hw.c

test.o : test.cpp
	gcc -c test.cpp

PHONY : clean
clean :
	rm -rf *.o myexpect
执行make后,可以正常生成myexpect程序。似乎gcc完全可以胜任g++的工作嘛。其实不然,那是因为我们的例子代码中没有使用libstdc++中的任何内容,比如将main.cpp做如下简单修改

#ifndef TEST_H
#	include "test.h"
#endif

#include <iostream>

using std::cout;
using std::endl;
int main(int argc, char** argv)
{
	do_test();

	cout<<"hi"<<endl;

	return 0;
}
这行上面这个Makefile后,会输出

gcc -c main.cpp
gcc -c hw.c
gcc -c test.cpp
gcc -o myexpect main.o hw.o test.o
main.o: In function `main':
main.cpp:(.text+0x1a): undefined reference to `std::cout'
main.cpp:(.text+0x1f): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
main.cpp:(.text+0x24): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)'
main.cpp:(.text+0x2c): undefined reference to `std::ostream::operator<<(std::ostream& (*)(std::ostream&))'
main.o: In function `__static_initialization_and_destruction_0(int, int)':
main.cpp:(.text+0x5a): undefined reference to `std::ios_base::Init::Init()'
main.cpp:(.text+0x69): undefined reference to `std::ios_base::Init::~Init()'
collect2: error: ld returned 1 exit status
make: *** [myexpect] Error 1
这一大段的错误,这是因为编译过程链接了libstdc的内容,而iostream在libstdc++中。为了解决这个问题,这样修改Makefile

myexpect : main.o hw.o test.o
	g++ -o myexpect main.o hw.o test.o

main.o : main.cpp
	gcc -c main.cpp

hw.o : hw.c
	gcc -c hw.c

test.o : test.cpp
	gcc -c test.cpp

PHONY : clean
clean :
	rm -rf *.o myexpect
用gcc去依据各文件类型生成相应的目标文件,最后用g++来指定链接libstdc++的内容。使用nm命令观察hw.o的内容

root@hu-virtual-machine:/home/hu/project/c_# nm hw.o 
0000000000000000 T get_hw
虽然hw.o是C型目标文件,不过对于myexpect程序来说,这个符号是唯一的,可以正常寻址,程序可以正常工作


以上就是C和C++混合编程总结的一些规律,nm工具是一个很好的调试工具,用它来观察编译后的目标文件中的符号有助于加深对C和C++处理符号的理解,谢谢观赏。



  • 14
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
《精通MATLAB与C/C++混合编程第3版》是一本专门介绍如何在MATLAB和C/C++之间进行混合编程的书籍。混合编程是指在MATLAB中调用C/C++代码,以提高程序的效率和性能。 这本书主要包含了以下内容:首先介绍了MATLAB和C/C++的基本知识,如MATLAB脚本语言和C/C++的语法、函数和变量的使用等。然后详细介绍了如何在MATLAB中调用C/C++代码,包括如何编写MEX文件(MATLAB可执行文件),以及如何在MATLAB环境中编译和运行这些文件。此外,还介绍了如何在MATLAB中使用C/C++的库函数和数据结构。 书中还讲解了一些高级的主题,如如何优化MATLAB和C/C++代码的性能、如何处理复杂的数据类型和多线程编程等。此外,还提供了一些实际案例和例子,帮助读者更好地理解和掌握混合编程的技巧和方法。 这本书的优点在于结合了MATLAB和C/C++的实际应用,介绍了大量的实际案例和技巧,对于想要学习如何在MATLAB和C/C++之间进行混合编程的人来说非常有用。无论是初学者还是有一定编程经验的人,都可以通过这本书提高自己的编程水平,提升自己的工作效率。 综上所述,《精通MATLAB与C/C++混合编程第3版》是一本非常实用的书籍,对于想要深入学习和应用MATLAB和C/C++混合编程的人来说是必备的参考资料。它不仅能够帮助读者了解MATLAB和C/C++之间的关系,还可以提升他们的编程水平和解决实际问题的能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值