calling c++ function from c - c++

I need to access a C++ function from C but I get some error like :-
/tmp/ccUqcSZT.o: In function `main':
main.c:(.text+0x5): undefined reference to `load_alert_to_db'
collect2: error: ld returned 1 exit status
My main.c code is:-
#include <stdio.h>
extern void load_alert_to_db(void);
int main(void){
/* Create empty queue */
load_alert_to_db();
return 0;
}
C++ code implementation db_manager.cpp is:-
#include <sstream>
#include <iostream>
#include <sstream>
#include <string>
#include <ctime>
#include <cstdlib>
#include <algorithm>
#include <time.h>
#include <cstring>
#include <fstream>
//using namespace oracle::occi;
#include <iostream>
using namespace std;
extern "C" void load_alert_to_db(void)
{
cout<<"db occi"<<endl;
}
makefile is:-
CC= g++
all:
$(CC) -c -Wall -Werror -fPIC db_manager.cpp
$(CC) -shared -o libdb_manager.so db_manager.o
gcc -L/home/oracle/Desktop/storage/ -Wall main.c -o data -ldb_manager
gcc -o data main.c
clean:
rm -f *.o data
so please help me which one is my problem. I am also include
export LD_LIBRARY_PATH=/home/oracle/Desktop/storage/:$LD_LIBRARY_PATH
environmental variable in .bash_profile

gcc -o data main.c
Not sure why you have this line in your makefile since it will compile main.c without reference to the previously created library and hence cause an undefined-symbol error such as the one you're seeing.
This is especially so, since you appear to have done it the right way on the preceding line:
gcc -L/home/oracle/Desktop/storage/ -Wall main.c -o data -ldb_manager
However, the entire point of using makefiles is so that it figures out the minimum necessary commands for you, based on dependencies. Lumping a large swathe of commands into a single rule tends to defeat that purpose. You would be better off making your rules a little more targeted, such as (untested but should be close):
all: data
data: main.o libdb_manager.so
gcc -o data main.o -ldb_manager
main.o: main.c
gcc -o main.o main.c
libdb_manager.so: db_manager.cpp
g++ -c -Wall -Werror -fPIC -o db_manager.o db_manager.cpp
g++ -shared -o libdb_manager.so db_manager.o
That way, if you make a small change to one part (like main.c), it doesn't have to go and compile/link everything in your build tree.

Your makefile seems to be completely broken and random, and you're not even linking the required object files. You can simplify this:
all:
$(CC) -c -Wall -Werror -fPIC db_manager.cpp
$(CC) -shared -o libdb_manager.so db_manager.o
gcc -L/home/oracle/Desktop/storage/ -Wall main.c -o data -ldb_manager
gcc -o data main.c
to just this:
all:
gcc -Wall -c main.c
g++ -Wall -c db_manager.cpp
g++ main.o db_manager.o -o data

this is what I needed to do:
Supposing the C++ function is called Debug::Write(str)
Then in your hpp file do the following:
#ifdef __cplusplus
extern "C" void DebugTmp(char *str);
#endif
Then in the corresponding cpp file do this:
void DebugTmp(char *str)
{
Debug::Write(str);
}
Then in your C file where you call DebugTmp define the prototype:
void DebugTmp(char *str);
then call it as below:
static void MyFunction( void )
{
DebugTmp("This is debug trace\n");
}

Related

C++ undefined reference in Makefile

I created my Makefile for a simple program but it returns undefined reference for class functions constantly:
g++ -c src/main.cpp -o lib/main.o
g++ -c src/functions.cpp -o lib/functions.o
g++ -c src/Circular.cpp -o lib/Circular.o
g++ lib/main.o -o bin/app.exe
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: lib/main.o:main.cpp:(.text+0x20): undefined reference to `Circular::Circular()'
collect2.exe: error: ld returned 1 exit status
make.exe: *** [app.exe] Error 1
Here is my Makefile:
app.exe: lib/main.o lib/Circular.o lib/functions.o
g++ lib/main.o -o bin/app.exe
lib/functions.o: src/functions.cpp
g++ -c src/functions.cpp -o lib/functions.o
lib/Circular.o: src/Circular.cpp
g++ -c src/Circular.cpp -o lib/Circular.o
lib/main.o: src/main.cpp
g++ -c src/main.cpp -o lib/main.o
Here is a short snippet of main.cpp:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <fstream>
#include <string>
#include "../include/Circular.h"
#include "../include/functions.h"
using namespace std;
int main(int argc, const char * argv[]) {
Circular item;
return 0;
}
Circular.h:
#include "node.h"
class Circular
{
public:
Circular();
node *start;
node *last;
int counter;
}
Circular.cpp:
#include "../include/Circular.h"
#include <iostream>
using namespace std;
Circular::Circular()
{
start = NULL;
last = NULL;
}
and node.h:
struct node
{
int data;
struct node *next;
struct node *prev;
};
I know the problem is about linker and with Makefile but even though I tried different possible solutions, somehow it doesn't work. Therefore, maybe someone can see the mistake I am making. Thanks!
I managed to create a Makefile from this source .
The Makefile looks like this:
CXX = g++
CXXFLAGS = -std=c++17 -Wall
LXXFLAGS = -std=c++17
OBJECTS = main.o Circular.o functions.o
TARGET = main
$(TARGET): $(OBJECTS)
$(CXX) $(LXXFLAG) $(OBJECTS) -o $(TARGET)
main.o: main.cpp Circular.cpp Circular.h functions.cpp functions.h
$(CXX) $(CXXFLAGS) -c main.cpp
Circular.o: Circular.cpp
$(CXX) $(CXXFLAGS) -c Circular.cpp
functions.o: functions.cpp
$(CXX) $(CXXFLAGS) -c functions.cpp
clean:
rm -f $(TARGET) $(OBJECTS)
And also added cout to you Circular constructor to check the execution as below:
#include "Circular.h"
#include <iostream>
using namespace std;
Circular::Circular()
{
start = NULL;
last = NULL;
cout << "Yes!" << endl;
}
Here's the result:
Output
Don't forget to put a semicolon for your Circular class in your Circular.h.
NOTE: If you aren't able to use make in cmd,use choco install make.
The Makefile should be structured to build the dependencies, then the final assembly into a .exe. Each path should be specified exactly as it is, not approximated:
app.exe: lib/main.o lib/Circular.o lib/functions.o
g++ lib/main.o lib/Circular.o lib/functions.o -o app.exe
lib/main.o: src/main.cpp
g++ -c src/main.cpp -o lib/main.o
lib/functions.o: src/functions.cpp
g++ -c src/functions.cpp -o lib/functions.o
lib/Circular.o: src/Circular.cpp
g++ -c src/Circular.cpp -o lib/Circular.o
The key here is be consistent and that includes things like the order of things specified in this file. Whatever order you pick, stick to it. This makes tracking down problems way easier.
If this project gets more complex you probably want to pivot to using a dependency tracking Makefile template instead of this homebrew one. Note how in those you don't need to specify a rule for each file, but instead a rule for each type of file, as in .cpp -> .o, and the rest happens automatically.

How to solve redefinition of main in makefile

I am trying to compile and link three files into an executable with a makefile, but seem to have redefined main or somehow goofed the compile/link process. The project is for a class, where the objective is to implement a linear feedback shift register, but we have to use a makefile.
Where have I redefined main? How do I alter my makefile to create my executable? I notice the error points to test.o as having redefined main, but I'm not sure why or how.
Error:
g++ -c main.cpp LFSR.cpp -Wall -Werror -ansi -pedantic
g++ -c test.cpp -Wall -Werror -ansi -pedantic
g++ main.o LFSR.o test.o -o ps2a -lboost_unit_test_framework
test.o: In function `main':
test.cpp:(.text+0xa3): multiple definition of `main'
main.o:main.cpp:(.text+0x0): first defined here
collect2: error: ld returned 1 exit status
Makefile:4: recipe for target 'ps2a' failed
make: *** [ps2a] Error 1
My makefile:
all: ps2a
ps2a: main.o LFSR.o test.o
g++ main.o LFSR.o test.o -o ps2a -lboost_unit_test_framework
LFSR.o: LFSR.cpp LFSR.hpp
g++ -c LFSR.cpp -Wall -Werror -ansi -pedantic
main.o: main.cpp LFSR.hpp
g++ -c main.cpp LFSR.cpp -Wall -Werror -ansi -pedantic
test.o: test.cpp
g++ -c test.cpp -Wall -Werror -ansi -pedantic
clean:
rm *.o ps2a
main.cpp:
#include "LFSR.hpp"
int main(){
}
LFSR.hpp
#include <string>
#include <iostream>
class LFSR{
public:
LFSR(std::string, int);
int step();
int generate(int k);
private:
std::string bitString;
int tapPos;
};
LFSR.cpp:
#include "LFSR.hpp"
void makeBitStringValid(std::string& str);
LFSR::LFSR(std::string str, int t){
}
int LFSR::step(){
return 0;
}
int LFSR::generate(int k){
return 0;
}
void makeBitStringValid(std::string& str){
}
test.cpp (Note, this is given by the instructor-- I'm not entirely sure how it works yet)
#include <iostream>
#include <string>
#include "LFSR.hpp"
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE Main
#include <boost/test/unit_test.hpp>
BOOST_AUTO_TEST_CASE(fiveBitsTapAtTwo) {
LFSR l("00111", 2);
BOOST_REQUIRE(l.step() == 1);
BOOST_REQUIRE(l.step() == 1);
BOOST_REQUIRE(l.step() == 0);
BOOST_REQUIRE(l.step() == 0);
BOOST_REQUIRE(l.step() == 0);
BOOST_REQUIRE(l.step() == 1);
BOOST_REQUIRE(l.step() == 1);
BOOST_REQUIRE(l.step() == 0);
LFSR l2("00111", 2);
BOOST_REQUIRE(l2.generate(8) == 198);
}
Do not provide own main because The Boost Unit Test Framework already provides one in your test.cpp with the lines:
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE Main
#include <boost/test/unit_test.hpp>
Dynamic library variant of the UTF
Unlike the static library variant function main() can't reside in the
dynamic library body. Instead this variant supplies default function
main() implementation as part of the header boost/test/unit_test.hpp
to be generated as part of your test file body. The function main() is
generated only if either the BOOST_TEST_MAIN or the BOOST_TEST_MODULE
flags are defined during a test module compilation. For single-file
test module flags can be defined either in a test module's makefile or
before the header boost/test/unit_test.hpp inclusion. For a multi-file
test module flags can't be defined in makefile and have to be defined
in only one of the test files to avoid duplicate copies of the
function main().

g++ -I duplicating libraries

I'm learning to program C++ in Linux, and I have the following problem:
I have 4 files: main.cpp, model.cpp, view.cpp and controller.cpp, each (except main) with their own header files. main.cpp includes model.h, view.h and controller.h, and view.h includes other libraries that are only relevant to it (necessary to run the graphic library). Those libraries are in different folders and have other dependencies on their own (that's why I don't want to move them). So, my makefile looks as follows:
model: model.cpp model.h
g++ -c model.cpp
view: view.cpp view.h
g++ -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads -I.. -c view.cpp
controller: controller.cpp
g++ -c controller.cpp
main: main.cpp
g++ -c main.cpp
and also a line to link all the files together (I didn't added it because I'm writing this on my Mac and copying it from the screen of my Raspberry Pi).
My problem is that when I try to compile them, all of them work, except for main, it tells me the following:
In file included from main.cpp:6:0:
view.h:4:23: fatal error: VG/openvg.h: No such file or directory
compilation terminated.
make: *** [main] Error 1
From what I can understand, when I compile view with "make view", it can find the files included without problem, because it has the paths in which it must look, but since "make main" doesn't have those paths, it doesn't know where to look for openvg.h. The problem is that if I add the paths to main, it tells me that there's multiple definitions for what's inside the library... Any help?
The #include VG/openvg.h is in /opt/vc/include and is included from view.h
When you make view you are including it from view.cpp which is compiled with -I/opt/vc/include
When you make main you are including it from main.cpp which is compiled without flags so it can't find the file.
You need to add the flags
main: main.cpp
g++ -c -I/opt/vc/include main.cpp
You may need the other flags as well, depending on what view.h includes.
The multiple definitions are caused by $(OPENVGLIBDIR)/fontinfo.h
which contains
Fontinfo SansTypeface, SerifTypeface, MonoTypeface;
so if you include that file in more than one object file and link them (main.o and view.o in this case) you will get multiple definitions.
Change it to
extern Fontinfo SansTypeface, SerifTypeface, MonoTypeface;
I then got Background etc undefined as libshapes is a C library. To get round this I changed
#include "fontinfo.h"
#include "shapes.h"
in view.h to
extern "C" {
#include "fontinfo.h"
#include "shapes.h"
}
and it builds for me (with references to model and controller removed).
In your makefile, the view/model/controller/main targets are making the .o files so they should be .o too. When you make test when no .o exists, it is looking for the .o target. If there isn't one in your makefile it will use the default which is a straight g++ -c.
Your make file should be like this:
test: model.o view.o controller.o main.o $(OPENVGLIBDIR)/libshapes.o $(OPENVGLIBDIR)/oglinit.o
g++ -o test view.o main.o model.o controller.o $(OPENVGLIBDIR)/libshapes.o $(OPENVGLIBDIR)oglinit.o -L/opt/vc/lib -L/opt/vc/include -lGLES -ljpeg
view.o: view.cpp
g++ -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads -I.. -c view.cpp
main.o: main.cpp
g++ -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads -I.. -c main.cpp view.cpp
model.o: model.cpp
g++ -c model.cpp
controller.o: controller.cpp
g++ -c controller.cpp
here are my files, the code seems to run fine if in main.cpp I include view.cpp instead of view.h, but I don't think that's what I'm supposed to be doing:
main.cpp
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <iostream>
#include "model.h"
#include "view.h"
#include "controller.h"
using namespace std;
int main() {
int n;
View view;
view.initialize();
view.drawBackground();
view.show();
std::cin >> n;
}
view.h:
#ifndef VIEW_H
#define VIEW_H
#include "VG/openvg.h"
#include "VG/vgu.h"
#include "fontinfo.h"
#include "shapes.h"
class View{
private:
int width, height;
public:
View();
int getWidth();
int getHeight();
void drawBackground();
void initialize();
void show();
};
#endif
view.cpp
#include "view.h"
View::View(){
int width, height;
VGfloat w2, h2, w;
}
int View::getWidth(){
return width;
}
int View::getHeight(){
return height;
}
void View::drawBackground(){
Background(0,0,0);
Stroke(255,255,255,1);
Fill(255,0,0,1.0);
Circle(width/2, height/2, 100);
}
void View::initialize(){
init(&width, &height);
Start(width, height);
}
void View::show(){
End();
}
Thanks A LOT for your help man! I've been fighting with this for the last couple of days (that's what I get for getting used to automatic compiling/linking). It's somewhat based on that example. I can make it run if I make each object by itself and then link them all together like this:
test: model.o view.o controller.o main.o $(OPENVGLIBDIR)/libshapes.o $(OPENVGLIBDIR)/oglinit.o
g++ -o test view.o main.o model.o controller.o $(OPENVGLIBDIR)/libshapes.o $(OPENVGLIBDIR)oglinit.o -L/opt/vc/lib -L/opt/vc/include -lGLES -ljpeg
view: view.cpp
g++ -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads -I.. -c view.cpp
main: main.cpp
g++ -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads -I.. -c main.cpp view.cpp
model: model.cpp
g++ -c model.cpp
controller: controller.cpp
g++ -c controller.cpp
if I do "make view" "make main" and then "make test" everything goes fine, but if I try "make test" without any object created prior to that I get fatal error: VG/openvg.h: No such file or directory when it's trying to compile view.cpp

Undefined reference during compilation

I would like to write a make file, but I'm quit newbie. I have the main file where I include the l_mpc.h helper.h written by me, also I'm using the gnuplot, because of this I need the gnuplot_i.hpp.
This is my make file
CPPFLAGS=-I /usr/local/include/eigen3
dc_motor_main.out : dc_motor_main.o
g++ -o main.out dc_motor_main.o
dc_motor_main.o: l_mpc.o helper.o
g++ $(CPPFLAGS) -c dc_motor_main.cpp l_mpc.o helper.o
gnuplot_i.o: gnuplot_i.hpp
g++ $(CPPFLAGS) -c gnuplot_i.hpp
l_mpc.o: l_mpc.cpp l_mpc.h
g++ $(CPPFLAGS) -c l_mpc.cpp
helper.o: helper.cpp helper.h
g++ $(CPPFLAGS) -c helper.cpp
clean:
rm *.o dc_motor_main.out
and the output is the following:
g++ -I /usr/local/include/eigen3 -c l_mpc.cpp
g++ -I /usr/local/include/eigen3 -c helper.cpp
g++ -I /usr/local/include/eigen3 -c dc_motor_main.cpp l_mpc.o helper.o
g++: warning: l_mpc.o: linker input file unused because linking not done
g++: warning: helper.o: linker input file unused because linking not done
g++ -o main.out dc_motor_main.o
dc_motor_main.o: In function `main':
dc_motor_main.cpp:(.text+0x3ab3): undefined reference to `SysMat::SysMat()'
dc_motor_main.cpp:(.text+0x40fa): undefined reference to `SysMat::calcMPCFi(int)'
The SysMat::SysMat() is in the l_mpc.h, Where do I make the mistake?
This is my header files:
main.cpp
#include <iostream>
#include <Eigen/Dense>
#include <sys/time.h>
#include "gnuplot_i.hpp"
#include "l_mpc.h"
#include "helper.h"
#define DEBUG 1
int main( int argc, char* argv[])
{ ....
helper.h
#include <iostream>
#include <Eigen/Dense>
#include <sys/time.h>
#include "gnuplot_i.hpp"
using namespace Eigen;
double now();
void plot_x(MatrixXd, Gnuplot *);
void plot_x(MatrixXd, float, Gnuplot *);
void plot_xy(MatrixXd, MatrixXd, Gnuplot *);
void plot_xy(MatrixXd, Gnuplot *);
template <typename T> int sgn(T val) {
return (T(0) < val) - (val < T(0));
}
l_mpc.h
#include <iostream>
#include <Eigen/Dense>
#include <sys/time.h>
#include "gnuplot_i.hpp"
using namespace Eigen;
class SysMat
{
public:
MatrixXd Fi;
MatrixXd Ga;
MatrixXd C;
MatrixXd Er;
private:
MatrixXd MPCFi;
MatrixXd MPCGa;
MatrixXd MPCGy;
public:
SysMat(MatrixXd, MatrixXd, MatrixXd);
SysMat();
~SysMat();
void calcMPCFi(int);
void calcMPCGa(int);
void calcMPCGy(int, int);
MatrixXd calcContSig(MatrixXd, MatrixXd, MatrixXd);
MatrixXd calcError(MatrixXd, MatrixXd, MatrixXd);
};
The mistake looks to be here
dc_motor_main.out : dc_motor_main.o
g++ -o main.out dc_motor_main.o
dc_motor_main.o: l_mpc.o helper.o
g++ $(CPPFLAGS) -c dc_motor_main.cpp l_mpc.o helper.o
should be
main.out : dc_motor_main.o l_mpc.o helper.o
g++ -o main.out dc_motor_main.o l_mpc.o helper.o
dc_motor_main.o: l_mpc.o helper.o
g++ $(CPPFLAGS) -c dc_motor_main.cpp
assuming that you want your executable file to be called main.out.
When you use the g++ -c option you are compiling only. The final step without -c is called linking, that should link together all the *.o files you have created by compiling each *.cpp file.
As Olaf says in his answer there are various ways you can make this less repetitive, but what is above is the basic steps however you do it.
Make already knows how to build object files out of appropriate sources. So, most of the time you need only define the dependencies and you can simplify the Makefile to
CPPFLAGS=-I /usr/local/include/eigen3
LDFLAGS = # insert linker flags, if needed
LDLIBS = # insert needed libraries here
OBJS = \
dc_motor_main.o \
gnuplot_i.o \
l_mpc.o \
helper.o \
dc_motor_main.out: $(OBJS)
g++ $(LDFLAGS) -o $# $(OBJS) $(LDLIBS)
gnuplot_i.o: gnuplot_i.hpp
l_mpc.o: l_mpc.h
helper.o: helper.h
clean:
rm $(OBJS) dc_motor_main.out
Keep in mind, that the commands must be prefixed by a tab character. Don't insert spaces instead.

Wrapping a C++ class in Python using SWIG

example.h:
#ifndef EXAMPLE_H
#define EXAMPLE_H
class Math {
public:
int pi() const;
void pi(int pi);
private:
int _pi;
};
#endif
example.cpp:
#include "example.h"
int Math::pi() const {
return this->_pi;
}
void Math::pi(int pi) {
this->_pi = pi;
}
example.swig:
%module example
%{
#define SWIG_FILE_WITH_INIT
#include "example.h"
%}
%include "example.h"
I then generate the wrappers, "example.py" and "example_wrap.c" using:
swig -python example.swig
When I try to compile the wrapper class using:
g++ -fPIC -c example.cpp example_wrap.c -I/usr/local/include/python2.6/
I get the following error:
example_wrap.cpp: In function "PyObject* Swig_var_Math_get()":
example_wrap.cpp:2725: error: expected primary-expression before "void"
example_wrap.cpp:2725: error: expected ")" before "void"
The Error is at the following line :
pyobj = SWIG_NewPointerObj(SWIG_as_voidptr(&Math), SWIGTYPE_p_class, 0 );
#define SWIG_as_voidptr(a) (void *)((const void *)(a))
Is it the right way to generate the wrapper class "example_wrap.c"?
I think the swig command should be "swig -c++ -python example.swig"
There's not enough information here to be sure what's wrong, but I have two ideas for things you can try.
Your g++ invocation is compiling a C source file as if it were C++. This is not guaranteed to work. Try instead
gcc -I/usr/local/include/python2.6 -fPIC -c example_wrap.c
gcc -I/usr/local/include/python2.6 -fPIC -c example.cpp
g++ -shared example_wrap.o example.o -o example.so
(yes, srsly, only use g++ for the link)
If that doesn't work, compile example_wrap.c like this:
gcc -I/usr/local/include/python2.6 -fPIC -c -save-temps example_wrap.c
That will fail the same way but will produce a file named example_wrap.i which is the result of preprocesing. It will be gigantic. Search that file for the function Swig_var_Math_get, and add to your question the complete text of that function (but nothing else).
Thanks for your replay!
The -C++ option generated the C++ class for the wrapper.
swig -c++ -v -python example.swig
I used g++ to compile the wrapper.
g++ -fPIC -c example.cpp example_wrap.cxx -I/usr/local/include/python2.6/
And the following command to buikd the shared object. Ofcourse, we need to remove the superflous includes (-I) and libraries (-L). The important flags are '-shared' and '-fPIC'.
g++ example_wrap.o example.o -L/u01/app/oracle/product/1020.full/lib -I/usr/local/ssl/include -L/usr/local/ssl/lib -lclntsh -lssl -lcrypto -ldl -L/usr/local/lib -L/lib64 -L/usr/local/lib/python2.6/ -lboost_system -lboost_filesystem -lboost_thread -lboost_date_time -lglog -lmodpbase64 -lpthread -ldl -lrt -shared -fPIC -o _example.so