Link To Library with C and C++ Bindings - c++

I am trying to determine if it is possible to link against a linux library with c and c++ bindings. I have an existing c++ project which is broken down into several libraries. I would like to extend these libraries with C bindings so that I can use them with cgo.
I am aware of how to mix c/c++ with extern "c" syntax. The problem that I have is in daisy chaining libraries. I've created a sample project which demonstrates my question:
https://github.com/Shelnutt2/c_cpp_linker_test
In this project we have hello.c, world.cpp both of which are built into a library called libwords . I can link libwords to libhelloworld without an issue. The problem occurs when trying to build main.cpp, which wants to call a c and c++ functions from libhelloworld (and thus the linked libwords)
Due to the linking differences of C++ vs C the main executable can not find the hello function
main.cpp:15: undefined reference to `hello'
Is it possible to link against the same library in this manner or do I need to break c-bindings into their own wrapper library?
In this example project I used shared libraries, but I'm open to static linking if that is possible.

You should link your application with both libraries. The exports are not transitive.
main: main.o libhelloworld.so
$(CXX) $< -L'$(CURDIR)' -lwords -lhelloworld -o $#
> gmake
c++ -Wall -g -O -fPIC -DC_LINK_TEST=1 -c -o helloworld.o helloworld.cpp
cc -Wall -g -O -fPIC -DC_LINK_TEST=1 -c -o hello.o hello.c
c++ -Wall -g -O -fPIC -DC_LINK_TEST=1 -c -o world.o world.cpp
c++ -Wall -g -O -fPIC -DC_LINK_TEST=1 -shared hello.o world.o -o libwords.so
c++ -Wall -g -O -fPIC -DC_LINK_TEST=1 -L'/usr/home/me/c_cpp_linker_test' -lwords -shared helloworld.o libwords.so -o libhelloworld.so
c++ -Wall -g -O -fPIC -DC_LINK_TEST=1 -c -o main.o main.cpp
#c++ main.o libhelloworld.so -o main
c++ main.o -L'/usr/home/me/c_cpp_linker_test' -lwords -lhelloworld -o main
> LD_LIBRARY_PATH=$LD_LIBRARY_PATH:`pwd` ./main
c gives us: hello
cpp gives us: hello world
>
Otherwise there is no problem with linking both C and C++ calling conventions, as the name mangling is different.
(never mind the change g++ to c++ - I use clang)

Related

problem with including fmt library in several cpp files

Good day!
I installed the fmt library in Ubuntu. Added it in my project
#include "fmt/core.h"
#include "fmt/format.h"
#include "fmt/format-inl.h"
to use fmt::format_int и fmt::format. I added library headers in several cpp files of my project. During linkage I got the mistake "multiple definition":
obj/container.o: In function fmt::v7::format_error::~format_error()': container.cpp:(.text+0x40e): multiple definition of fmt::v7::format_error::~format_error()'
obj/line.o:line.cpp:(.text+0x40e): first defined here
I've read something about this mistake. It is recommended to divide declaration and implementation in h and cpp files, to set some status to objects that causes mistake and so on. But all this recommendations imply editing of library (not my!) code!
What is wrong?
I do the following
compilation of files - one by one
g++ -std=c++11 -Wall -o obj/line.o -c /home/...//line.cpp
g++ -std=c++11 -Wall -o obj/container.o -c /home/...//container.cpp
g++ -std=c++11 -Wall -o obj/geometryObject.o -c /...//geometryObject.cpp
g++ -std=c++11 -Wall -o obj/model.o -c /home/...//model.cpp
g++ -std=c++11 -Wall -o obj/point.o -c /home/...//point.cpp
g++ -std=c++11 -Wall -o obj/main.o -c /home/...//main.cpp
Linking - error here
g++ -std=c++11 -Wall -o myapp obj/line.o obj/container.o obj/geometryObject.o obj/model.o obj/point.o obj/main.o
You shouldn't be including fmt/format-inl.h because it's an internal header. Please see the documentation for the list of public headers and what they provide.

C++ - Makefile using g++

I have made a Makefile for my CMSC 202 course project, 'Blackjack'. It does everything I need it to and it works perfectly. You may be asking why I posted here then, this is because I have no idea how it works and I didn't use any other resources but myself to create it.
Here is my Makefile code.
# Object files to either reference or create
OBJECTS = Proj2.o Blackjack.o Deck.o Card.o Hand.o Player.o
# The executable file that will be created at the end
EXEC = Proj2.out
# The flags to use for compilation
FLAGS = -Wall
# The code compiler to use for compilation
CC = g++
# Perform action on all object files (May or may not exist)
all: $(OBJECTS)
$(CC) $(FLAGS) -o $(EXEC) $(OBJECTS)
Here is the terminal output when I call make in the terminal.
g++ -c -o Proj2.o Proj2.cpp
g++ -c -o Blackjack.o Blackjack.cpp
g++ -c -o Deck.o Deck.cpp
g++ -c -o Card.o Card.cpp
g++ -c -o Hand.o Hand.cpp
g++ -c -o Player.o Player.cpp
g++ -Wall -o Proj2.out Proj2.o Blackjack.o Deck.o Card.o Hand.o Player.o
Can anyone tell me how the .o files are being compiled? It does not look like they are being prompted to be compiled with that g++ -c -o $.o $.cpp command anywhere in the Makefile. Nor did I state to use any .cpp files.
Thank you in advance for your help.
Edit
Thanks to all your great help, this is now the terminal output I receive when using make.
g++ -Wall -c -o Proj2.o Proj2.cpp
g++ -Wall -c -o Blackjack.o Blackjack.cpp
g++ -Wall -c -o Deck.o Deck.cpp
g++ -Wall -c -o Card.o Card.cpp
g++ -Wall -c -o Hand.o Hand.cpp
g++ -Wall -c -o Player.o Player.cpp
g++ -Wall -o Proj2.out Proj2.o Blackjack.o Deck.o Card.o Hand.o Player.o
Thank you so much to all of you who have contributed.
Make has a set of implicit rules (see here for a reference). For instance
Compiling C++ programs
`n.o' is made automatically from `n.cc' or `n.C' with a command of the form
`$(CXX) -c $(CPPFLAGS) $(CXXFLAGS)'.
Most make's will also use this rule for .cpp files.
When make sees there's a x.o requirement for one of your targets, it will try to see if it can generate x.o using implicit rules, and in your case find it can do it starting from a .cpp file.
This Makefile uses implicit rules which are a great way to reduce duplication.
By default the first target will be built, here all. It depends on a number
of object files listed in a variable $OBJECTS, e.g. Proj2.o who's
dependencies aren't listed in the Makefile. Now if make sees an input file in the current directory
with a matching name, e.g. Proj2.cpp it will try
to build Proj2.o from it (there are other implicit rules for sources in
other languages). Proj2.o would then be built by default with the command
$(CXX) $(CXXFLAGS) -c -o Proj2.o
where $(CXX) the name of the C++ compiler (g++ in your case).
The explicit build step for all assembles all the object files into the
target executable.
Looking at above build command you'll notice a small problem in your Makefile. Since the flags to the C++ compiler are given in a variable FLAGS and not the standard CXXFLAGS no warnings will be emitted when building the object files. Using the standard name would fix this (you do want warnings, maybe even more than -Wall gives you).

compiling ncurses code with gcc -lncurses flag seems to not be working

I'm writing a terminal based Tetris game using ncurses. I've segregated all of the ncurses code into a file called tetrisUI.c which i include a header file for in my main.c source file. When I compile all of the ncurses functions raise compiler errors. I have included ncurses.h in my source file and I'm using the -lncurses flag in gcc. I'm compiling from a makefile with the following contents:
Tetris : tetris.o main.o tetrisUI.o
gcc tetris.o main.o tetrisUI.o -o Tetris
tetrisUI.o : tetrisUI.c
gcc -std=c99 -c tetrisUI.c -lncurses
tetris.o : tetris.c tetris.h
gcc -std=c99 -c tetris.c
main.o : main.c tetris.h tetrisUI.h
gcc -std=c99 -c main.c
I was able to compile a few short test programs using ncurses just fine. This is my first attempt at using ncurses and my first significant c program (I've done a little c++ in school). I have a hunch that my problem has something to do with my makefile but I'm a noob at using those too.
Use -lncurses at the link stage not at the compile stage:
gcc tetris.o main.o tetrisUI.o -o Tetris -lncurses
You can simplify your Makefile by using default macros and rules:
CFLAGS = -std=c99 # C compiler flags
LDLIBS = -lcurses # curses
Tetris : tetris.o main.o tetrisUI.o # make does a "$(CC) $(CFLAGS) -o $# $^ $(LDLIBS)" on its own
That's all you need. The following definitions and rules can be completely omitted - make does the right thing by default:
CC = gcc # C compiler name
tetrisUI.o : tetrisUI.c tetrisUI.h # make does a "$(CC) $(CFLAGS) -o $# $<" on its own
tetris.o : tetris.c tetris.h
main.o : main.c tetris.h tetrisUI.h
A bit of explanation: $# is whatever is being built, $< is the first dependency, $^ is all of them. Judicious use of this makes for less typing (and less idiotic errors, where you add a dependency and don't process it; or omit a dependency (and thus don't redo the build if it changes)). Take a look at the make manual, if you have GNU make, its info file has lots of detailed examples and tips.

GLEW based program does not compile

I am trying to use GLEW in a program I'm creating, but my compiler will not compile it, instead it throws a ton of errors at this line gcc -g -c glew.c -o glew.o. This is my Makefile:
MY_LIBS =
glewex: glew.o main.o glew.h
g++ main.o glew.o glew.h -o glewex $(MY_LIBS)
glew.o: glew.c
gcc -g -c glew.c -o glew.o
main.o: main.cpp
g++ -g -c main.cpp -o main.o
It simply outputs hundreds of errors that look like this:
__glewActiveTexture redeclared without dllimport attribute: previous import ignored [ -Wattributes ]
Try this:
gcc -g -DGLEW_STATIC -c glew.c -o glew.o
That should prevent DLL import/export decorations from getting added to the declarations.
You don't want to add the library source files to the compiler input of your project. You should add the library to the list of linker inputs; either statically (libglew.a) or dynamic (-lglew).
I.e. either
gcc -o … -lglew
or
gcc -o … libglew.a
When linking GLEW statically you must add -DGLEW_STATIC to the compiler options generating the compilation units (.o files)

C++ program gets undefined reference to a dynamic C library during linking

I've created a dynamic networking library in C. When I try to link it in my C++ program I get an undefined reference the first time I call one of my functions in the library. What I can't understand is that I created a little test program in C that uses the library and it links just fine.
Could someone help with my problem? Here are the steps I've taken to create my library and link it.
Library creation:
Code my library
Compile with the line: gcc -c -fPIC -g -Wall ./libnet.c
Link my library object file and create the shared object file with the line: gcc -shared -o libnet.so -g -Wall ./libnet.o
Move my library to the appropriate folders and set LD_LIBRARY_PATH:
I copy my library to two directories. One directory is the test C program that links properly and one is the C++ program that doesn't link properly.
I set the environment variable LD_LIBRARY_PATH to both the directories that use the library
Compile and link my program:
Code my program
Compile all my .cpp files with the line: g++ -c -g -Wall ./
Link together all my object files and the shared library to create my program with the line: g++ -o -g -Wall -L./ -lnet
Here is the make file that I use. Maybe I have something wrong in here?
PPFLAGS = -g -Wall
TARGET = msgfrwdserver
OBJS = msgfrwdserver.o
msgfrwdhelper.o msgfrwd.o climsgfrwd.o
LIBS = libnet.so
CPPLP =
-L/usr/home/chris/development/legends/servers/monitor
-L/usr/home/chris/development/legends/servers/msgfrwd
CPPFILES = ./msgfrwdserver.cpp
./msgfrwdhelper.cpp
./classes/msgfrwd.cpp
./classes/climsgfrwd.cpp
CPPIP = -I./classes
-I/usr/home/chris/development/legends/libnet
all: ${OBJS} ${TARGET}
${TARGET}: ${OBJS} ${LIBS}
g++ -o
${TARGET} ${PPFLAGS} -L./ -lnet
${CPPIP} ${OBJS}
msgfrwdserver.o: ./msgfrwdserver.cpp
g++ -c ${PPFLAGS} ${CPPIP}
./msgfrwdserver.cpp
msgfrwdhelper.o:
./msgfrwdhelper.cpp
g++ -c ${PPFLAGS}
./msgfrwdhelper.cpp
msgfrwd.o:
./classes/msgfrwd.cpp
g++ -c
${PPFLAGS} ./classes/msgfrwd.cpp
climsgfrwd.o: ./classes/climsgfrwd.cpp
g++ -c ${PPFLAGS} ${CPPIP}
./classes/climsgfrwd.cpp
clean: rm
-rf ${TARGET} *.o *~ .core ./classes/~
I really have no idea what the problem could be. Any help would be much appreciated. Do I have to do something differently to get a C library to work with a C++ program?
Sorry that the make file is messy. I didn't exactly translate well when I tried to block quote it or say it was a code sample.
C library functions must have en extern "C" definition in order to call them from C++ to turn of name-mangeling.
extern "C"
{
int test();
}
With the extern , the the Microsoft C++ compiler will look for the symbol "_test", otherwise it will look for "?test##YAHXZ" (The C++ name-mangeled version of int test() )