linux下c程序c++程序混合编译,c程序中调用c++程序,c语言项目与c++语言项目的合并

2019-07-13 09:05发布

博主目的是把两个开源项目合并到一起,但是一个是c编写,一个是c++编写,在linux环境下实现两个项目的融合,以及互相的调用。 首先编译,先贴出来我的makefile文件: GPU=1
OPENCV=1
DEBUG=0


ARCH= --gpu-architecture=compute_30 --gpu-code=compute_30


VPATH=./src/
EXEC=darknet
OBJDIR=./obj/


CC=gcc
GCC=g++ -std=c++11 #兼容 c++11
NVCC=nvcc
OPTS=-Ofast
LDFLAGS= -lm -pthread -lstdc++ 
COMMON= 
CFLAGS=-Wall -Wfatal-errors 


ifeq ($(DEBUG), 1) 
OPTS=-O0 -g
endif


CFLAGS+=$(OPTS)


ifeq ($(OPENCV), 1) 
COMMON+= -DOPENCV
CFLAGS+= -DOPENCV
LDFLAGS+= `pkg-config --libs opencv` 
COMMON+= `pkg-config --cflags opencv` 
endif


ifeq ($(GPU), 1) 
COMMON+= -DGPU -I/usr/local/cuda/include/
CFLAGS+= -DGPU
LDFLAGS+= -L/usr/local/cuda/lib64 -lcuda -lcudart -lcublas -lcurand
endif


OBJ=gemm.o ...//c项目的


OBJ+=plate_locate.o ...//c++项目的

ifeq ($(GPU), 1) 
OBJ+=convolutional_kernels.o ...//c项目的

OBJS = $(addprefix $(OBJDIR), $(OBJ))
DEPS = $(wildcard src/*.h) Makefile


all: obj results $(EXEC)


$(EXEC): $(OBJS)
$(CC) $(COMMON) $(CFLAGS) $^ -o $@ $(LDFLAGS)


$(OBJDIR)%.o: %.c $(DEPS)
$(CC) $(COMMON) $(CFLAGS) -c $< -o $@


$(OBJDIR)%.o: %.cpp $(DEPS)
$(GCC) $(COMMON) $(CFLAGS) -c $< -o $@


$(OBJDIR)%.o: %.cu $(DEPS)
$(NVCC) $(ARCH) $(COMMON) --compiler-options "$(CFLAGS)" -c $< -o $@


obj:
mkdir -p obj
results:
mkdir -p results


.PHONY: clean


clean:
rm -rf $(OBJS) $(EXEC)




inux下c程序c++程序混合编译,c程序中调用c++程序,c语言项目与c++语言项目的合并
编译.c用gcc,编译.cpp用g++,最后的链接:gcc -lstdc++,采用静态链接。关于为什么编译要分别使用gcc,g++,因为他们c和c++的编译方式不同 所以想要在c中调用c++,就必须把c++程序按照c的编译方式来编译生成静态链接库(.o文件)。对于函数调用,编译器只要知道函数的参数类型和返回值以及函数名就可以进行编译连接。那么为了让C调用C++接口或者是说C++调用C接口,就必须是调用者和被调用者有着同样的编译方式。这既是extern "C"的作用,extern “C”是的程序按照C的方式编译。
问题在于如何在c中调用c++的函数,下面列出两种方式,使用情况请看官自己分辨: 第一种方法是用一个接口做桥梁。 比如在原本的c++项目中有类hello: 1.myclass.h
  1. #include   
  2. using namespace std;  
  3.   
  4. class Myclass {  
  5. public:  
  6.     Myclass(){}  
  7.     ~Myclass(){}  
  8.     void Operation();  
  9. };  

2.hello.cpp
  1. #include "myclass.h"  
  2. using namespace std;  
  3. void Myclass::Operation()  
  4. {  
  5.     cout << "hello c++" <
  6. }  

我们用一个接口做桥梁, 3 interface.h [cpp] view plain copy  print?在CODE上查看代码片派生到我的代码片
  1. #ifdef __cplusplus  
  2. extern "C"{  
  3. #endif  
  4.   
  5. void interface();  
  6.   
  7. #ifdef __cplusplus  
  8. }  
  9. #endif  

4 interface.cpp [cpp] view plain copy  print?在CODE上查看代码片派生到我的代码片
  1. #include "myclass.h"  
  2. #include "interface.h"  
  3.   
  4. #ifdef __cplusplus  
  5. extern "C"{  
  6. #endif  
  7.   
  8. void interface()  
  9. {  
  10.     Myclass obj;  
  11.     obj.Operation();  
  12. }  
  13.   
  14. #ifdef __cplusplus  
  15. }  
  16. #endif  
然后在c语言项目中的main函数这样调用:
5 main.c [cpp] view plain copy  print?在CODE上查看代码片派生到我的代码片
  1. #include "interface.h"  
  2.   
  3. int main()  
  4. {  
  5.     interface();  
  6.     return 0;  
  7. }  

第二种方法是直接引用。 在c++项目中: 1.tools.cpp #include "tools.h" #ifdef __cplusplus extern "C"{ #endif using namespace std; void hello1(){ cout<<"hello 1"< void hello2(){cout<<"hello 2"< #ifdef __cplusplus  
}  
#endif  

2.tools.h

#ifdef __cplusplus  
#include
#include
#endif  


#ifdef __cplusplus  
extern "C"{  
#endif  

void hello1(); void hello2();
#ifdef __cplusplus  
}  
#endif  

然后在c项目中调用如下: 3.main.c extern void hello1(); extern void hello2(); int main(){
hello1(); hello2(); } 在这种方法中,要注意的几点:1,在tools.h中,#include 也要放进#ifdef __cplusplus #endif中,否则在编译链接时,会出现找不到iostream的错误。 2,在main.c中用extern来声明这两个来自c++的外部函数,而不需要在开头#include 关于#ifdef __cplusplus  #endif 以及 extern “C”的作用: http://blog.csdn.net/owldestiny/article/details/5772916 可以参考这篇博客:http://blog.csdn.net/owldestiny/article/details/5772916