2007年8月2日星期四

c++与c的混合编程

项目涉及到在linux下c++和c混合编程的情况,下面转载师弟解决该问题的过程。
需求来源:

将C++编写的数据挖掘程序整合到原来的系统中,作为一个普通的线程进行周期性调用。

方法:

将C++中的int main()函数,即进行频繁项集挖掘的主函数,改为C语言中的一个普通外部函数进行调用,比如本项目中改为void do_datamining(),在原系统的main.c中新开一线程调用do_datamining()进行数据挖掘。


具体步骤:
1、用g++编译KMeantest.cpp AprioriSets.cpp KMean.cpp Data.cpp为对应的.o文件
2、ar命令将这几个.o文件压缩为静态连接库文件cpplib.a
3、用gcc编译main.c send.c whitelist.c 几个文件为对应的.o文件

最后,用g++将cpplib.a与原系统用gcc编译的main.o send.o whitelist.o 连接生成可执行文件nsbic_antiddos

在与C++编写的数据挖掘模块进行合并时,出现了如下的错误:

g++ /home/jwf/antiddos/obj/*.o /home/jwf/antiddos/obj/cpplib.a -o nsbic_antiddos -lpcap -lmysqlclient -lpthread -lm
/home/jwf/antiddos/obj/main.o(.text+0x133): In function `main':
: undefined reference to `do_datamining'
collect2: ld returned 1 exit status
make: *** [nsbic_antiddos] Error 1

提示do_datamining函数不存在

原因是C++中由于存在函数重载机制,因此g++编译的函数目标代码在.o文件中的格式与C语言用gcc生成的目标代码中的函数名格式不一致,从而会出现以上的错误。

解决的方法是:
1、在C++代码中,关于do_datamining函数声明语句,应该写为extern "C" void do_datamining(),这样g++在编译这句代码的时候,会按照C语言的格式去生成目标代码。
2、在main.c中关于do_datamining()的声明写为extern void do_datamining()表明这个函数是一个外部函数
3、重新编译整个系统,进而实现代码的整合。

数据挖掘模块原来main函数所处的文件KMeantest.cpp中,代码修改如下

extern "C" void do_datamining();
void do_datamining()
{
……

}

原来系统中main.c中对do_datamining函数做如下声明:

extern void do_datamining();


重新编译整个系统,实现了C语言代码与C++代码的合并

附:Makefile部分关于gcc 与g++混合编译的语句

原系统中c文件的编译:

gcc -c main.c
gcc -c whitelist.c
gcc -c send.c

数据挖掘模块的cpp文件编译:

g++ -c -o KMeantest.o KMeantest.cpp
g++ -c AprioriSets.cpp
g++ -c Data.cpp
g++ -c Item.cpp
g++ -c KMean.cpp
g++ -c PropertyMan.cpp
ar -cur cpplib.a KMeantest.o AprioriSets.o Data.o Item.o KMean.o PropertyMan.o


将用g++编译的代码与用gcc编译的代码合并的语句:

g++ /home/jwf/antiddos/obj/*.o /home/jwf/antiddos/obj/cpplib.a -o nsbic_antiddos -lpcap -lmysqlclient -lpthread -lm
补充:
2)参考:MSDN 'Mixed-Language Programming Topics' 介绍了原理

没有评论: