Undefined reference to function errors, using C and C++ together - c++

I have run into a problem while using C and C++ code together. The 'make' command returns "Undefined reference to function" for all functions in SPConfig.c and SPLogger.c, when called from SPImageProc.cpp
#include sections of these relevant files are given below:
SPLogger.c
#include "SPLogger.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
SPConfig.h
#ifndef SPCONFIG_H_
#define SPCONFIG_H_
#include <stdbool.h>
#include <stdio.h>
#include "SPLogger.h"
//Functions definitions
#endif /* SPCONFIG_H_ */
SPConfig.c
#include "SPConfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
SPImageProc.h
#ifndef SPIMAGEPROC_H_
#define SPIMAGEPROC_H_
#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <vector>
extern "C" {
#include "SPConfig.h"
#include "SPPoint.h"
}
namespace sp {
//Class and function definitions
}
SPImageProc.cpp
#include <cstdlib>
#include <cassert>
#include <cstring>
#include <opencv2/xfeatures2d.hpp>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <cstdio>
#include "SPImageProc.h"
extern "C" {
#include "SPLogger.h"
}
Makefile
CC = gcc
CPP = g++
#put all your object files here
OBJS = main.o SPImageProc.o SPPoint.o
#The executabel filename
EXEC = SPCBIR
INCLUDEPATH=/usr/local/lib/opencv-3.1.0/include/
LIBPATH=/usr/local/lib/opencv-3.1.0/lib/
LIBS=-lopencv_xfeatures2d -lopencv_features2d \
-lopencv_highgui -lopencv_imgcodecs -lopencv_imgproc -lopencv_core
CPP_COMP_FLAG = -std=c++11 -Wall -Wextra \
-Werror -pedantic-errors -DNDEBUG
C_COMP_FLAG = -std=c99 -Wall -Wextra \
-Werror -pedantic-errors -DNDEBUG
.PHONY: all clean
all: $(EXEC)
$(EXEC): $(OBJS)
$(CPP) $(OBJS) -L$(LIBPATH) $(LIBS) -o $#
main.o: main.cpp #put dependencies here!
$(CPP) $(CPP_COMP_FLAG) -I$(INCLUDEPATH) -c $*.cpp
#a rule for building a simple c++ source file
#use g++ -MM SPImageProc.cpp to see dependencies
SPImageProc.o: SPImageProc.cpp SPImageProc.h SPConfig.h SPPoint.h SPLogger.h
$(CPP) $(CPP_COMP_FLAG) -I$(INCLUDEPATH) -c $*.cpp
#a rule for building a simple c source file
#use "gcc -MM SPPoint.c" to see the dependencies
SPPoint.o: SPPoint.c SPPoint.h
$(CC) $(C_COMP_FLAG) -c $*.c
clean:
rm -f $(OBJS) $(EXEC)
Some of Makefile errors:
SPImageProc.o: In function `sp::ImageProc::initFromConfig(sp_config_t*)':
SPImageProc.cpp:(.text+0xc8): undefined reference to `spConfigGetPCADim'
SPImageProc.cpp:(.text+0xf2): undefined reference to `spLoggerPrintError'
SPImageProc.cpp:(.text+0x12c): undefined reference to `spConfigGetNumOfImages'
I have implemented the functions in their respective C and CPP files. I have tried a lot to fix it myself and looked it up on Stack Overflow for similar problems but couldn't find a solution. Please help.

You are not linking SPLogger.o and SPConfig.o
Or even compiling them for that matter.
You need to add make rules for SPLogger.o and SPConfig.o similar to SPImageProc.o and you need to add them to OBJS.

Related

Problems with Makefile and compiling a cpp file marks error in a function declared in other file

I have problems with my Makefile.
I used the following structure to generate the .o files of each cpp file, but does not work (using c works without problems, I cant find what is the problem)
%.o : %.cpp %.h
g++ -c -Wall $< -o $#
And the error while compiling is a function is declared in a separated h and cpp file and added to the main file. But when I try to generate de .o file of main.cpp marks error in the function.
The command I used to compile the main.cpp -> g++ -c main.cpp -o main.o
The error that gives me is:
main.cpp: In function ‘int main(int, char)’:
main.cpp:9:9: error: ‘number’ was not declared in this scope9 | number();
This is the compiler that I used for it:
g++ (Ubuntu 11.2.0-19ubuntu1) 11.2.0
Linux 5.15.0-40-generic
Please, anyone could explain me if I'm doing wrong of something is left
/*main.cpp*/
#include <iostream>
#include "numb.h"
using namespace std;
int main(int argc, char* argv[])
{
cout<<"Run"<<endl;
number();
cout<<"end Run"<<endl;
return 0;
}
/*end main.cpp*/
/*numb.cpp*/
#include <iostream>
#include "numb.h"
using namespace std;
int number()
{
cout<<"Function"<<endl;
return 117;
}
/*end numb.cpp*/
/*numb.h*/
#include <iostream>
#define NUMB_H
#ifndef NUMB_H
int number();
#endif
/*end numb.h*/
You got the header guard in the wrong order.
Instead of:
#define NUMB_H
#ifndef NUMB_H
It is supposed to be:
#ifndef NUMB_H
#define NUMB_H
When compiling specify both CPP files, because #include fixes compile errors, but does not fix linker errors
g++ -c main.cpp numb.cpp ...
As a rule, in header files nothing have to be outside the #define guards:
/*numb.h*/
#define NUMB_H
#ifndef NUMB_H
#include <iostream>

Linking C++ object files embedded with Python

I have a C++ constructor file (formatting_SQ.cpp) of a header file formatting_SQ.h which I want to link to other constructor files of header files (neat.cpp nnode.cpp link.cpp etc...-> neat.h nnode.h link.h) in order to have formatting_SQ.o.
Then, I want to link my main.cpp file with this formatting_SQ.o file. The problem is: formatting_SQ is embedded with python, and as far as my understanding goes, C++ embedded with Python needs the compiling flag -lpython3.6m on Linux: such flag requires a reference to a main() function, which I don't have in formatting_SQ.cpp because it's a constructor file meant to be an object file.
So I first tried to create object files for each constructor file and then link everything together at once:
g++ -c -O3 -Wall -fPIC -fopenmp -std=c++14 -lstdc++ `python3 -m pybind11 --includes` *.cpp
g++ -o the_executable neat.o nnode.o link.o trait.o gene.o network.o innovation.o organism.o species.o genome.o population.o formatting_SQ.o main.o -fopenmp -O3 -Wall -fPIC `python3 -m pybind11 --includes` -lpython3.6m
Here comes my first question: Are these command right or is there eventually a compilation flag missing ? This gives me a segmentation fault as I try to execute ./the_executable.
Then, I tried to compile formatting_SQ.cpp independently with all other constructor files, but as expected, this doesn't work because there is no reference to main in formatting_SQ.cpp.
g++ -o temp_formatting neat.o nnode.o link.o trait.o gene.o network.o innovation.o organism.o species.o genome.o population.o formatting_SQ.o -fopenmp -O3 -Wall -fPIC `python3 -m pybind11 --includes` -lpython3.6m
So here comes my second question: how could I create a python embedded object file linking formatting_SQ.cpp with all other constructor files without having this undefined reference to main error ?
formatting_SQ.cpp
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
#include <pybind11/stl.h>
#include <Python.h>
#include <omp.h>
#include "formatting_SQ.h"
#include "neat.h"
#include "network.h"
#include "link.h"
#include "nnode.h"
#include "trait.h"
#include "gene.h"
#include "genome.h"
#include "innovation.h"
#include "organism.h"
#include "species.h"
#include "population.h"
namespace py = pybind11;
py::module compile_data = py::module::import("initialize");
main.cpp
#include <pybind11/embed.h>
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
#include <pybind11/stl.h>
#include <Python.h>
#include "formatting_SQ.h"
#include <omp.h>
namespace py = pybind11;
int main(int argc, char** argv){
....
So after some long hours of research I can conclude that the compilation method is correct but BE EXTREMELY CAREFULL with where you declare your import modules from python, because this was the problem for me
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
#include <pybind11/stl.h>
#include <Python.h>
#include <omp.h>
#include "formatting_SQ.h"
#include "neat.h"
#include "network.h"
#include "link.h"
#include "nnode.h"
#include "trait.h"
#include "gene.h"
#include "genome.h"
#include "innovation.h"
#include "organism.h"
#include "species.h"
#include "population.h"
namespace py = pybind11;
py::module compile_data = py::module::import("initialize"); DON'T DO THIS its wrong !!!
You must declare your modules locally otherwise there be some conflicts in the namespace as the same module may be imported more than once and this causes the segmentation fault.

How to use opengl in static lib?

I'm trying to create a static shader library with OpenGL.
I want it to be as portable as possible (Windows Linus Android ...).
For this propose i made a header what includes gl and glext:
OpenGL.hpp
...
#define GL_GLEXT_PROTOTYPES
#if defined(OS_WINDOWS)
#ifdef _MSC_VER
#include <windows.h>
#endif
#include <GL/gl.h>
#include <GL/glext.h>
#elif defined(OS_LINUX)
#include <GL/gl.h>
#include <GL/glext.h>
...
And Shader.hpp
...
class Shader
{
unsigned int m_id;
public:
Shader();
...
};
...
And Shader.cpp
...
#include <Shader.hpp>
#include <OpenGL.hpp>
Shader::Shader()
{
m_id = glCreateProgram();
...
}
...
Then complied Shader.cpp to Shader.o and with ar created libShader.a.
After that on android i can compile like that:
g++ -I ./include -c main.cpp -o main.o
g++ -L ./lib -o main main.o -lShader -lSDL2 -lGLESv1_CM -lGLESv2
And it runs flawless.
But on windows when i link
g++ -L ./lib -o main.exe main.o -lShader -lSDL2 -lglew32 -lopengl32 -lglu32
G++ gives lib\libShader.a(Shader.o):Shader.cpp undefined reference to glCreateProgram#8
error.
On windows main.cpp looks like this:
#include <GL/glew.h>
#include <Shader.hpp>
...
int main()
{
Shader shader1;
...
GLuint test_id_for_main = glCreateProgram();
...
}
...
The wierd thing is test_id_for_main works (if i comment out the Shader-s) without link error.
What did i do incorrectly on windows?
I ended up creating my own OpenGL headers and loading the functions with wgl/glx/dlopen

String parameters

I'm trying to use swig to interface with c++, and I'm having problems using a std::string& parameter. This is on Fedora 19 with golang 1.1-2, swig 2.0.10-1, and gcc 4.8.1-1.
I don't know C++. I do know C, and had hoped to wing it. At any rate, _swig_wrap_pinput ends up with a null pointer.
What am I overlooking?
Here's my test case:
st.i
%module st
%{
#include <string>
extern void pinput(std::string& pstring);
%}
%include <std_string.i>
#include <string>
void pinput(std::string& pstring);
st.cxx
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <iostream>
void pinput(std::string& pstring) {
std::cout<<pstring;
}
stmain.go
package main
import (
"st"
)
func main() {
myLit:="This is a test."
st.Pinput(&myLit)
}
Makefile
SWIGOBJS = st_gc.c st_wrap.cxx st.go
all: st.so st.a
$(SWIGOBJS): st.i
swig -go -c++ -intgosize 64 st.i
st.o: st.cxx
g++ -c -fpic -g -o st.o st.cxx
st_wrap.o: st_wrap.cxx
g++ -c -fpic -g -o st_wrap.o st_wrap.cxx
st.so: st_wrap.o st.o
g++ -shared st_wrap.o st.o -o st.so
st_gc.6: st_gc.c
/usr/lib64/golang/pkg/tool/linux_amd64/6c -I /usr/lib64/golang/pkg/linux_amd64 st_gc.c
st.6: st.go
/usr/lib64/golang/pkg/tool/linux_amd64/6g st.go
st.a: st.6 st_gc.6
go tool pack grc st.a st.6 st_gc.6
test: stmain
stmain: stmain.6
/usr/lib64/golang/pkg/tool/linux_amd64/6l stmain.6
stmain.6: stmain.go
/usr/lib64/golang/pkg/tool/linux_amd64/6g stmain.go
Since the question was originally asked both Go and SWIG have updated. I will post a solution that worked for me (Go 1.3.3, SWIG 3.0.2). As you can see, the difference to the original post is minimal.
The most recommended approach is to use go build. It knows nowadays to look for *.swig and *.swigcxx files, and runs both SWIG and GCC/G++ automatically based on the information found in the swig interface file.
stmain.go
package main
import (
"st" // This will be created by SWIG
)
func main() {
myLit:="This is a test."
st.Pinput(myLit)
}
st/st.h
ifndef ST_H
#define ST_H
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <iostream>
void pinput(const std::string& pstring);
#endif
st/st.cpp
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <iostream>
void pinput(const std::string& pstring) {
std::cout << pstring;
std::cout << std::endl; // Without endl the stdout doesn't get flushed for me -> no output
}
st/st.go
package st
// Without any Go file in the directory the go build will fail
st/st.swigcxx
%module st
%include "std_string.i"
%include "st.h"
%{
extern void pinput(const std::string& pstring);
%}
void pinput(const std::string& pstring);
To build & run
// Quick'n'dirty version
# go build stmain.go
# ./stmain
This is a test.
#
Alternatively you can build the same sources manually with 6g/c/l/swig/gotool, for example my simplified version:
Makefile:
all:
make -C st
/usr/local/go/pkg/tool/linux_amd64/6g -I st stmain.go
/usr/local/go/pkg/tool/linux_amd64/6l -o stmain -extldflags -lstdc++ -L st stmain.6
clean:
rm -f *.6 6.out
make clean -C st
test: stmain
st/Makefile:
all: clean
swig -go -intgosize 64 -c++ -soname st.so st.swigcxx
g++ -c st.cpp -o st.o
g++ -c st_wrap.cxx -o st_wrap.o
/usr/local/go/pkg/tool/linux_amd64/6c -I /usr/local/go/pkg/linux_amd64/ -D _64BIT st_gc.c
/usr/local/go/pkg/tool/linux_amd64/6g st.go
go tool pack grc st.a st.6 st_gc.6 st.o st_wrap.o
clean:
rm -f *.6
rm -f *.a
rm -f *.so
rm -f *.cxx
rm -f *.c
rm -f *.o

Not possible to compile. Headers files.Enclosed own objects definition

Here I am with a similar question as the last time, and for which I could not find any answer.
Note that I consider important: Normally I compile my programs in opencv with the next command:
g++ -o def program.cpp `pkg-config --cflags opencv` `pkg-config --libs opencv`
This line will create an executable whose name will be def and that I will be able to use.
I am working in a project, and as it was getting bigger, I had to define some objects, just to make everything easier and possible to handle. I create one object from the files: homogra.cpp and homogra.h the comand I used for it was:
g++ -c homogra.cpp `pkg-config --cflags opencv` `pkg-config --libs opencv`
Then, I wrote in my program.cpp the line #include "homogra.h"
And I compile like:
g++ -o def program.cpp homogra.o `pkg-config --cflags opencv` `pkg-config --libs opencv`
Until now everything is working fine.
Then I create a second object(with the same compilation line as for homogra, but this time with segmentator.cpp and segmentator.h), i wrote the line #include "segmentator.h",(in program.cpp) and I compile like:
g++ -o def program.cpp .o segmentator.o `pkg-config --cflags opencv` `pkg-config --libs opencv`
Now it is not working, and it is not recognising segmentator. I checked already if segmentator was working and everything works fine if homogra is the only include in the program.cpp.
I notice something strange. If I change the lines and I write before,in the #include lines, #include "segmentator.h" and then #include "homogra.h", then the compiler, with the same line for compiling :
g++ -o def program.cpp homogra.o segmentator.o `pkg-config --cflags opencv` `pkg-config --libs opencv`
is only recognising this time segmentator and not homogra. It is maybe a little difficult to understand, I tried to explained it as better as possible.
Any help!?
Many thanks in advance.
Here is homogra.h:
using namespace cv;
using namespace std;
#ifndef _NAMES_H
#define _NAMES_H
class homogra {
public:
Mat matCalculation( Mat img, Mat img2);
void printMatrix(Mat matrix);
};
#endif
In homogra.cpp I have all the tipical includes and homogra.h:
#include <stdio.h>
#include <stdlib.h>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <sstream>
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "homogra.h"
And then the functions explained.
Object 2 is segmentator.h
using namespace cv;
using namespace std;
#ifndef _NAMES_H
#define _NAMES_H
class segmentator {
public:
void search(Mat img,vector<std::vector<cv::Point> >& contours);
void similar(vector<std::vector<cv::Point> >& contours,vector<std::vector<cv::Point> >& contours2,vector<int>& idx);
vector<Mat> separate(Mat img,Mat img2,vector<std::vector<cv::Point> >& contours,vector<std::vector<cv::Point> >& contours2,vector<int> idx);
};
#endif
And in segmentator.cpp I have again all the same includes, except homogra.h and instead of this one I have segmentator.h.
Program.cpp is image_reg.cpp:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <sstream>
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "homogra.h"
#include "segmentator.h"
using namespace cv;
using namespace std;
int main(int argc, char ** argv )
{ //Here is the code where I try to invoque two instances of homogra and segmentator.
}
If I let homogra.h as the first to be read in the includes list of image_reg.cpp then only homogra.h is recognised, if I let at the first position segmentator, then only segmentator.h instances would be created and homogra. h would not be recognised.
Thanks
Your include header guards are wrong. They should be unique, using the name of the source file, rather than just _NAMES_H.
So in homogra.h you should have this:
#ifndef HOMOGRA_H
#define HOMOGRA_H
...
#endif
...and in segmentator.h, you should have this
#ifndef SEGMENTATOR_H
#define SEGMENTATOR_H
...
#endif
Also, it's really bad practice to have a using namespace xxx; in a header file. You make it very difficult for your headers to coexist with others.
As Jonathan Wakely points out, beginning symbols with underscores is not a great idea, either.