Using a function written in C ++ in c-code

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

Header file:

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

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

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

I get 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 a linker, then it works fine. But the gcc linker gives me a problem.
  • I think the problem is with changing the name of the g ++ function, and gcc does not control function names (characters).
  • So, is there any compiler flag that, if possible, would have avoided a name change.
  • The reason for avoiding the g ++ linker is because it treats the link as a C ++ style, but the underlying code is in C, so an error may occur when calling the code.

Please someone suggest a solution.

+6
source share
5 answers

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

Use

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

instead, link everything together using the g++ linker and automatically set default values ​​for the linked libstc++.a .

Otherwise, you will need to specify -lstc++ as an additional library explicitly.


Also, if you are developing a pure c-API for your C ++ code, you should have

  #include <iostream> 

in the source file functions.cpp . Remove the standard C ++ headers with functions.h .


Please do not use using namespace std; in C ++ header files. It tends to cause namespace conflicts of all unexpected kinds (no one knows about all the names used in namespace std ).

In any case, it should not appear in a clean c-API header file.


If you want to have a mixed c / C ++ header file, put all of the special C ++ statements in the C ++ containment shells:

  #ifdef __cplusplus #include<iostream> class xyz; // A c++ forward declaration #endif 
+10
source

You must either link the program using g++ , or manually specify the libstdC ++ (s) library.

+6
source

Usually you need to link your C program using the C ++ library with the C ++ compiler (e.g. g++ ), and you probably need to link the standard C ++ library. Be careful:

  • static or global data that needs some non-trivial C ++ constructor (for example, std::cout ) - which should conceptually be run before entering your C main function. See also GCC function attributes , in particular constructor and visibility attributes.
  • C ++ functions throw exceptions that are not caught by C ++ code. If your C program calls a C ++ function that throws an exception that doesn’t get there, you might be in trouble .... (possibly undefined behavior or premature termination). This can happen when new is called in the process of running out of memory.
  • C ++ functions returning aggregation is not POD (but it will be difficult for you to declare such a function on the C side; declaring a C structure with all fields of C ++ data elements struct will not always be sufficient or correct, because the C ++ type requires a call of its destructor and because it can add a vtable pointer, etc.)
  • name mangling and calling conventions . You should probably declare each C ++ function visible C code as extern "C"

Stricto sensu, C ++ is designed to interact with a subset of C, but not the opposite.

It is possible to compile your C code using the C ++ compiler (and fix all incompatibilities) - for example. with g++ -std=c++11 -Wall -Wextra -g ...- could be easier. If your C code base is small (less than 100 thousand source lines), you can even consider porting it to C ++ and gradually use C ++ idiomatically. Keep in mind that C ++ 11 and C11 (or C99) are different languages ​​(which have limited and partial compatibility).

In practice, the link is used by g++ . In almost every case, this will not add errors. If so, compile all your code with g++ and rename all C source files as C ++ files (for example, your .c suffix will become .cc ) and recompile it all as C ++ (of course, correcting your "C" "until it makes the C ++ compiler happy).

+2
source

The reason for avoiding the g ++ linker is because it treats the link as a C ++ style, but the base code is in C, so it may introduce some error when calling the code

This is simply not so.

By the time you get to the linking stage, the difference between C and C ++ is pretty much academic: you are linking objects to machine code, not C or C ++.

What you need to know is a call of conventions and distorted names, but if this leads to incompatibilities in your program, you will know about it during the link. He will not introduce silent errors if something is not very, very wrong.

Thus, “this may lead to some error when calling the code” is wrong, and you can go ahead and contact g++ , as everyone else does. :) Because the only difference with your C ++ code is that it refers to the standard C ++ library and runtime, which you simply cannot do.

+2
source

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

That is why you should use g++ .

I think the problem is with changing the name of the g ++ function and gcc does not change the names of the functions (characters).

When compiling C ++ code, the mangling name is used. When compiling C code, the name is not used. This has nothing to do with bindings that don't care about whether characters have malformed names or not.

So, is there any compiler flag that could avoid, if possible, a name change.

This question is based on the false assumption that the name mangling has something to do with the binding.

The reason for avoiding the g ++ linker is because it treats the link as a C ++ style, but the underlying code is in C, so an error may occur when calling the code.

The linker does not need the language in which the code was originally written. It just binds the compiled code.

If the C code had to be linked differently than the C ++ code, or there would be some possible error, then what you are trying to do would be impossible - there would be no way to link the final executable. But since we all know that C and C ++ code can be safely linked on smart platforms like yours, you should be worried about issues that don't exist.

+2
source

Source: https://habr.com/ru/post/984805/


All Articles