C和CPP混合编译遇到的问题

​ 一个工程中需要用.c和.cpp文件连接生成一个可执行文件。在项目实践中,经常遇到C和C++混合编程的情况。

一、C和CPP混合编译的Makefile文件编写

将C和C++文件混合在一起编译成可执行文件,makefile文件如下:

.PHONY: all clean

SOURCE  := $(shell find ./ -name "*.c") 		#当前目录下.c文件
SOURCE  += $(shell find ../common -name "*c")	#共享目录下.c文件
SOURCECPP  := $(shell find ./ -name "*.cpp")	#当前目录下.cpp文件
OBJS3    := $(SOURCE:%.c=%3.o) 					#由于需要使用三个不同版本的库,所以生成三个.O
OBJS4    := $(SOURCE:%.c=%4.o) 
OBJSN4    := $(SOURCE:%.c=%N4.o) 
OBJSCPP3    := $(SOURCECPP:%.cpp=%3.o) 
OBJSCPP4    := $(SOURCECPP:%.cpp=%4.o) 
OBJSCPPN4    := $(SOURCECPP:%.cpp=%N4.o) 


#DEPS    := $(shell find ./ -name "*.h")

BUILD_BIN := ../../bin
#target you can change test to what you want
TARGET3      := $(BUILD_BIN)/v2xcenter3			#目标文件
TARGET4      := $(BUILD_BIN)/v2xcenter4
TARGETN4     := $(BUILD_BIN)/v2xcentern4
#compile and lib parameter

CC      := /home/ubuntu/SDK_REPO/prebuilt/toolchain/gcc-4.9-2016.02-x86_64_arm-linux-gnueabi/bin/arm-linux-gnueabi-gcc				
CPP		:= /home/ubuntu/SDK_REPO/prebuilt/toolchain/gcc-4.9-2016.02-x86_64_arm-linux-gnueabi/bin/arm-linux-gnueabi-g++
LIBS    :=  -L../../lib -lpthread -lssl -lcrypto -lmosquitto -lubox  -lubus -ljson-c -luci -lzlog -lpcap -ljsonxml					#库
LDFLAGS :=
DEFINES :=
INCLUDE := -I./ -I../../include/libubox/ -I../../include/libubus/ -I../../include/json-c/ -I../../include/libuci/ -I../../include/pcap	-I../../include -I../common 
-I../../include/jsonxml/						#头文件


#不同版本的库文件
LIBS3    := $(LIBS) -lasncodecv3				
LIBS4    := $(LIBS) -lasncodec
LIBSN4    := $(LIBS) -lasncodecv4_new

INCLUDE3 := $(INCLUDE) -I../../include/asn1codecv3 
INCLUDE4 := $(INCLUDE) -I../../include/asn1codec
INCLUDEN4 := $(INCLUDE) -I../../include/asn1codecv4_new

#编译参数
CFLAGS3  := -g -Wall $(DEFINES) $(INCLUDE3)			
CFLAGS3CPP  := -g -Wall -std=gnu++11 -fpermissive $(DEFINES) $(INCLUDE3)
CFLAGS4  := -g -Wall $(DEFINES) $(INCLUDE4)
CFLAGS4CPP  := -g -Wall -std=gnu++11 -fpermissive $(DEFINES) $(INCLUDE4)
CFLAGSN4  := -g -Wall $(DEFINES) $(INCLUDEN4)
CFLAGSN4CPP  := -g -Wall -std=gnu++11 -fpermissive $(DEFINES) $(INCLUDEN4)
CFLAGS  := -g -Wall $(DEFINES) $(INCLUDE)
CFLAGSCPP  := -g -Wall -std=gnu++11 -fpermissive $(DEFINES) $(INCLUDE)

all: $(TARGET3) $(TARGET4)  $(TARGETN4) $(VS_TARGET3) $(VS_TARGET4)  $(VS_TARGETN4) $(VC_TARGET)


$(TARGET3) : $(OBJS3) $(OBJSCPP3)
	$(CPP) $(CFLAGS3CPP) -o $(TARGET3) $(OBJS3) $(OBJSCPP3) $(LDFLAGS) $(LIBS3)
	
$(TARGET4) : $(OBJS4) $(OBJSCPP4)
	$(CPP) $(CFLAGS4CPP) -o $(TARGET4) $(OBJS4) $(OBJSCPP4) $(LDFLAGS) $(LIBS4)
	
$(TARGETN4) : $(OBJSN4) $(OBJSCPPN4)
	$(CPP) $(CFLAGSN4CPP) -o $(TARGETN4) $(OBJSN4) $(OBJSCPPN4) $(LDFLAGS) $(LIBSN4)	
	
%.o : %.c $(DEPS)
	$(CC) $(CFLAGS) -c $< -o $@ 
	
%3.o : %.c $(DEPS)
	$(CC) $(CFLAGS3) -c $< -o $@ -D VERSION3

%4.o : %.c $(DEPS)
	$(CC) $(CFLAGS4) -c $< -o $@ -D VERSION4
	
%N4.o : %.c $(DEPS)
	$(CC) $(CFLAGSN4) -c $< -o $@ -D VERSIONN4


%.o : %.cpp $(DEPS)
	$(CPP) $(CFLAGSCPP) -c $< -o $@ 
	
%3.o : %.cpp $(DEPS)
	$(CPP) $(CFLAGS3CPP) -c $< -o $@ -D VERSION3

%4.o : %.cpp $(DEPS)
	$(CPP) $(CFLAGS4CPP) -c $< -o $@ -D VERSION4

%N4.o : %.cpp $(DEPS)
	$(CPP) $(CFLAGSN4CPP) -c $< -o $@ -D VERSIONN4

clean:
	rm -f $(OBJS) $(OBJS3) $(OBJS4) $(OBJSN4) $(VS_OBJS3) $(VS_OBJS4) $(VS_OBJSN4) $(TARGET3) $(TARGET4) $(TARGETN4) $(VS_TARGET3) $(VS_TARGET4) $(VS_TARGETN4) $(VC_TARGET) $(OBJSCPP4) $(OBJSCPPN4) $(OBJSCPP3)
	

二、解决C和CPP混合编译出现undefined reference to的问题

​ 相对简单的混合编译头文件如上,其中编译链接的时候可能会出现undefined reference to的问题,这是因为cpp编译器和c编译本身不是同一个编译器,C和CPP采用不同的编译器,C++编译器在编译.cpp文件时生成的函数名与C编译器在编译.c文件时生成的函数名是不一样的,导致C++代码无法直接调用C的代码,两者混用是会产生不兼容的情况。

​ 解决办法如下:

​ 1、确保C和C++采用的是同类型的编译器,比如C用的是GCC,而CPP采用的是G++;

​ 2、在C的头文件中将C++需要调用的所有函数声明添加extern "C"即可解决;如果反过来在CPP的头文件中将C需要调用的所有函数声明添加extern "C"也可解决。

#ifndef AAAA_H
#define AAAA_H

#ifdef __cplusplus
extern "C" {
#endif

#include<stdio.h>

void  fun();//混合调用的函数

#ifdef __cplusplus
}
#endif/* End of the 'extern "C"' block */

 

#endif
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐