我正在开发一个项目,其中有些人已经用C ++编写代码,我们必须在C代码中使用它。所以我尝试按照测试编写一个测试程序来演示相同的内容:
头文件是:
#ifndef h_files_n
#define h_files_n
#include<iostream>
#ifdef __cplusplus
extern "C" {
#endif
void add_func(int, int);
#ifdef __cplusplus
}
#endif
#endif
cpp文件是:
#include"h_files.h"
void add_func(int num, int nums)
{
std :: cout << "The addition of numbers is : "<< num+nums << std endl;
}
c文件是:
#include<stdio.h>
#include"h_files.h"
int main()
{
printf("We are calling the C function form C++ file.\n");
add_func(10,15);
return 0;
}
makefile是:
CC = gcc
inc = -I include
vpath %.c src
vpath %.cpp src
vpath %.o obj
all : $(addprefix obj/,functions.o main.o) run
run : main.o functions.o
$(CC) -o bin/$@ $^
obj/%.o : %.cpp
$(CXX) -c $(inc) $^ -o $@ -libstdc++
obj/%.o : %.c
$(CC) -c $(inc) $^ -o $@
.PHONY : clean
clean :
-rm -f obj/* bin/*
我收到以下错误:
g++ -c -I include src/functions.cpp -o obj/functions.o
gcc -c -I include src/main.c -o obj/main.o
gcc -o bin/run obj/main.o obj/functions.o
obj/functions.o: In function `add_func':
functions.cpp:(.text+0x1e): undefined reference to `std::cout'
functions.cpp:(.text+0x23): 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*)'
functions.cpp:(.text+0x2d): undefined reference to `std::ostream::operator<<(int)'
functions.cpp:(.text+0x32): 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> >&)'
functions.cpp:(.text+0x3a): undefined reference to `std::ostream::operator<<(std::ostream& (*)(std::ostream&))'
obj/functions.o: In function `__static_initialization_and_destruction_0(int, int)':
functions.cpp:(.text+0x68): undefined reference to `std::ios_base::Init::Init()'
functions.cpp:(.text+0x77): undefined reference to `std::ios_base::Init::~Init()'
collect2: error: ld returned 1 exit status
make: *** [run] Error 1
请有人建议解决方案。
答案 0 :(得分:10)
$(CC) -o bin/$@ $^
使用
run : main.o functions.o
$(CXX) -o bin/$@ $^
而是使用g++
链接器将所有内容链接在一起,并自动设置链接的libstc++.a
库的默认值。
否则,您需要明确指定-lstc++
作为附加库。
另外,如果您正在为c ++代码设计一个纯c-API,那么您应该拥有
#include <iostream>
仅在functions.cpp
源文件中的语句。从functions.h
删除c ++标准标题。
请不要在c ++头文件中使用using namespace std;
。它很容易调用所有意外类型的命名空间冲突(没有人知道namespace std
中使用的所有名称)。
无论如何,它不应出现在纯c-API头文件中。
如果您想要一个混合 c / c ++ API头文件,请在c ++保护中放置 所有 c ++特定语句:
#ifdef __cplusplus
#include<iostream>
class xyz; // A c++ forward declaration
#endif
答案 1 :(得分:6)
您应该通过g++
链接程序或手动指定libstdc ++库。
答案 2 :(得分:2)
您通常应该使用C ++库和C ++编译器(如g++
)链接您的C程序,并且您可能需要链接标准C ++库。是(否则)小心:
std::cout
) - 在进入C main
函数之前,应该在概念上运行 。另请参阅GCC function attributes,特别是constructor
和visibility
属性。new
时可能会发生这种情况。struct
的所有数据成员字段的C结构将不会总是足够或者更正,因为C ++类型需要调用析构函数,因为它可能会添加一些vtable指针等...)extern "C"
Stricto sensu,C ++旨在与C的子集互操作,但不是相反的。
也许使用C ++编译器编译C代码(并修复所有不兼容性)-e.g.与g++ -std=c++11 -Wall -Wextra -g
...-可能会更容易。如果您的C代码库很小(少于100K源代码行),您甚至可以考虑将其移植到C ++,并逐步使用C ++。请注意,C++11和C11(或C99)是不同的语言(碰巧有一些有限的和部分 >兼容性。)
在实践中,使用g++
链接。几乎在所有情况下,这都不会增加错误。如果是,请使用g++
编译所有代码,并将所有C源文件重命名为C ++文件(例如,您的.c
文件后缀变为.cc
)并将整个内容重新编译为C ++(当然,通过纠正你的“C”程序,直到它使C ++编译器开心。)
答案 3 :(得分:2)
避免使用g ++链接器的原因是它将链接视为C ++样式,但基本代码在C中,因此它可能会在调用代码时引入一些错误
这根本不是真的。
当你进入链接阶段时,C和C ++之间的差异在很大程度上是学术性的:你在机器代码中链接对象,而不是C或C ++程序
您需要注意的是调用约定和错位名称,但如果这会在您的程序中引入不兼容性,那么您将在链接中了解它-时间。除非出现非常非常错误的事情,否则它不会引入无声的错误。
所以,“它可能会在调用代码中引入一些错误”错误,你可以像其他人一样继续与g++
链接。 :)因为与C ++代码唯一不同的是它引用了标准库和C ++运行库,这是你不能没有的。
答案 4 :(得分:2)
如果我使用g ++作为链接器,那么它工作正常。但是gcc链接器给了我这个问题。
这就是你应该使用g++
。
正如我想到的那样,问题是g ++的函数名称错误,而gcc不会破坏函数名称(符号)。
编译C ++代码时,使用名称修改。编译C代码时,不使用名称修改。这与链接没有关系,链接不关心符号是否有错位。
因此,如果可能的话,还有任何编译器标志可以避免名称损坏。
这个问题是基于错误的假设,即名称修改与链接有关。
避免使用g ++链接器的原因是它将链接视为C ++样式,但基本代码是C语言,因此可能会在调用代码时引入一些错误。
链接器不关心最初编写代码的语言。它只链接已编译的代码。
如果C代码必须与C ++代码链接不同,或者存在一些可能的错误,那么您尝试做的事情将是不可能的 - 没有办法链接最终的可执行文件。但是既然我们都知道C和C ++代码可以在像你这样的敏感平台上安全地链接在一起,那么你必须担心不存在的问题。