简体   繁体   中英

Using function written in c++ in c code

I am working on a project in which some people have already written code in C++ and we have to use it in our code in C. So I have tried following test to write a test program which demonstrates the same:

The header file is:

 #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 file is :

#include"h_files.h"

void add_func(int num, int nums)
{
    std :: cout << "The addition of numbers is : "<< num+nums << std endl;
}

The c file is :

#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 is :

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/*

I am getting the following error:

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
  • If I use g++ as linker then It works fine. But gcc linker gives me the problem.
  • As I think of the problem is the function name mangling by g++ and gcc does not mangles the functions name(symbols).
  • So is there any compiler flag that would avoid name mangling if possible.
  • The reason for avoiding g++ linker is It treats the linking as C++ style but the base code is in C so It may introduce some bug in calling code.

Please somebody suggest the solution.

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

Use

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

instead to link everything together using the g++ linker, and have the defaults for the linked libstc++.a library set automatically.

Otherwise you'll need to specify -lstc++ as additional library explicitely.


Also if you're designing a pure c-API for your c++ code you should have the

 #include <iostream>

statement in the functions.cpp source file only. Remove c++ standard headers from functions.h .


Please don't use using namespace std; in c++ header files generally. It's prone to invoke namespace clashes of all unexpected kinds (no one knows about all of the names used in the namespace std ).

It should not appear in a pure c-API header file anyway.


If you want to have a mixed c/c++ API header file, put all of the c++ specific statements within the c++ guards:

 #ifdef __cplusplus
 #include<iostream>

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

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

You generally should link your C program using a C++ library with a C++ compiler (like g++ ), and you very probably need to link the standard C++ library. Be (otherwise) careful about:

  • static or global data which needs some non-trivial C++ constructor (eg std::cout ) - which conceptually should be run before entering your C main function. See also GCC function attributes , notably constructor and visibility attributes.
  • C++ functions throwing exceptions which are not caught by C++ code. If your C program calls a C++ function which throws an exception which is not caught, you could be in trouble.... (probable undefined behavior, or premature termination). This may happen when new is invoked in an out-of-memory process.
  • C++ functions returning non POD aggregate (but you'll have trouble in declaring such a function on the C side; declaring a C struct with all the data member fields of the C++ struct won't be always enough or correct, because the C++ type requires its destructor to be called, and because it may add some vtable pointer, etc...)
  • name mangling and calling conventions . You probably should declare every C++ function visible by C code as extern "C"

Stricto sensu, C++ is designed to be interoperable with a subset of C, but not the converse.

Perhaps compiling your C code with a C++ compiler (and fixing all the incompatibilities) -eg with g++ -std=c++11 -Wall -Wextra -g ...- could be easier. If your C code base is small (less than 100K source lines), you could even consider porting it to C++, and progressively using C++ idiomatically. Be aware that C++11 and C11 (or C99) are different languages (which happen to have some limited and partial compatibility).

In practice, link using g++ . In almost every cases, this won't add bugs. If it does, compile all your code using g++ and rename all your C source files as C++ files (eg your .c file suffix becoming .cc ) and recompile the whole thing as C++ (of course by correcting your "C" program till it makes the C++ compiler happy).

The reason for avoiding g++ linker is It treats the linking as C++ style but the base code is in C so It may introduce some bug in calling code

That's simply not true.

By the time you get to the link stage, the difference between C and C++ is largely academic: you're linking objects in machine code , not C or C++ programs.

What you do need to be aware of is calling conventions and mangled names , but if that introduces an incompatibility in your program then you'll know about it at link-time. It won't introduce silent bugs unless something is very, very wrong.

So, "it may introduce some bug in calling code" is wrong and you may go ahead and link with g++ like everybody else does. :) Because the only other difference with your C++ code is that it is referencing the standard library and C++ runtime, which you simply cannot do without.

If I use g++ as linker then It works fine. But gcc linker gives me the problem.

That's why you should use g++ .

As I think of the problem is the function name mangling by g++ and gcc does not mangles the functions name(symbols).

When compiling C++ code, name mangling is used. When compiling C code, name mangling is not used. This has nothing to do with linking which doesn't care whether the symbols have mangled names or not.

So is there any compiler flag that would avoid name mangling if possible.

That question is based on the false assumption that name mangling has anything to do with linking.

The reason for avoiding g++ linker is It treats the linking as C++ style but the base code is in C so It may introduce some bug in calling code.

The linker doesn't care about the language the code was originally written in. It just links the compiled code.

If C code had to be linked differently from C++ code or there would be some possible bug, then what you are attempting to do would be impossible -- there would be no way to link the final executable. But since we all know C and C++ code can be linked together safely on sensible platforms like yours, you must be worried about problems that don't exist.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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