繁体   English   中英

在c代码中使用c ++编写的函数

[英]Using function written in c++ in c code

我正在开发一个项目,其中一些人已经用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
  • 如果我使用g ++作为链接器,那么它工作正常。 但是gcc链接器给了我这个问题。
  • 我想到的问题是g ++的函数名称变形,而gcc不会破坏函数名称(符号)。
  • 那么有没有任何编译器标志可以避免名称损坏,如果可能的话。
  • 避免g ++链接器的原因是它将链接视为C ++样式,但基本代码在C中,因此它可能会在调用代码时引入一些错误。

请有人建议解决方案。

$(CC) -o bin/$@ $^

采用

run : main.o functions.o
    $(CXX) -o bin/$@ $^

而是使用g++链接器将所有内容链接在一起,并具有链接libstc++.a的默认值libstc++.a自动设置库。

否则,您需要明确指定-lstc++作为附加库。


此外,如果您正在为您的c ++代码设计纯c-API,那么您应该拥有

 #include <iostream>

仅在functions.cpp源文件中的语句。 functions.h删除c ++标准头文件。


请不要using namespace std; 通常在c ++头文件中。 它很容易调用所有意外类型的命名空间冲突(没有人知道namespace std使用的所有名称)。

它无论如何都不应出现在纯c-API头文件中。


如果您想要一个混合的 c / c ++ API头文件,请将所有 c ++特定语句放在c ++保护中:

 #ifdef __cplusplus
 #include<iostream>

 class xyz; // A c++ forward declaration
 #endif

您应该通过g++链接程序或手动指定libstdc ++库(ies)。

您通常应该使用C ++库和C ++编译器(如g++ )链接您的C程序,并且您可能需要链接标准C ++库。 是(否则)小心:

  • 静态或全局数据需要一些非平凡的C ++ 构造函数 (例如std::cout ) - 在概念上应该进入C main函数之前运行。 另请参阅GCC函数属性 ,尤其是constructorvisibility属性。
  • C ++函数抛出未被C ++代码捕获的异常。 如果你的C程序调用一个C ++函数抛出一个未被捕获的异常,你可能会遇到麻烦....(可能是未定义的行为,或者是提前终止)。 当在内存不足的进程中调用new时,可能会发生这种情况。
  • C ++函数返回非POD聚合(但是你在C方面声明这样的函数时会遇到麻烦;用C ++ struct所有数据成员字段声明一个C struct将不会总是足够或正确,因为C ++类型需要调用析构函数,因为它可能会添加一些vtable指针等...)
  • 名称修改调用约定 您可能应该将C代码可见的每个C ++函数声明为extern "C"

Stricto sensu,C ++旨在与C的子集互操作,但不是相反的。

也许使用C ++编译器编译C代码(并修复所有不兼容性)-eg与g++ -std=c++11 -Wall -Wextra -g ...-可能更容易。 如果您的C代码库很小(少于100K源代码行),您甚至可以考虑将其移植到C ++,并逐步使用C ++。 请注意, C ++ 11C11 (或C99)是不同的语言(碰巧有一些有限的部分兼容性)。

在实践中, 使用g++链接 几乎在所有情况下,这都不会增加错误。 如果是这样,使用g++编译所有代码并将所有C源文件重命名为C ++文件(例如.c文件后缀变为.cc )并将整个内容重新编译为C ++(当然通过更正“C”程序直到它使C ++编译器感到高兴。

避免使用g ++链接器的原因是它将链接视为C ++样式,但基本代码是C语言,因此它可能会在调用代码时引入一些错误

这根本不是真的。

当你进入链接阶段时,C和C ++之间的差异在很大程度上是学术性的:你在机器代码中链接对象 ,而不是C或C ++程序。

您需要注意的是调用约定错位名称 ,但如果这会在程序中引入不兼容性,那么您将在链接时知道它。 除非出现非常非常错误的情况,否则它不会引入静默错误。

因此,“它可能会在调用代码中引入一些错误”是错误的 ,你可以像其他人一样继续使用g++链接。 :)因为与C ++代码唯一不同的是它引用了标准库和C ++运行库,这是你不能没有的。

如果我使用g ++作为链接器,那么它工作正常。 但是gcc链接器给了我这个问题。

这就是你应该使用g++的原因。

我想到的问题是g ++的函数名称变形,而gcc不会破坏函数名称(符号)。

编译C ++代码时,使用名称修改。 编译C代码时,不使用名称修改。 这与链接没有关系,链接不关心符号是否有错位。

那么有没有任何编译器标志可以避免名称损坏,如果可能的话。

这个问题是基于错误的假设,即名称修改与链接有关。

避免g ++链接器的原因是它将链接视为C ++样式,但基本代码在C中,因此它可能会在调用代码时引入一些错误。

链接器不关心最初编写代码的语言。它只链接已编译的代码。

如果C代码必须与C ++代码链接不同或者存在一些可能的错误,那么您尝试做的事情将是不可能的 - 没有办法链接最终的可执行文件。 但是,既然我们都知道C和C ++代码可以在像你这样的敏感平台上安全地链接在一起,那么你必须担心不存在的问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM