I try to include my self built .so library in the test.cpp file.
When I try to make the test.cpp file I get this exception:
root#airdrop:/home/pi/naza-interface/examples# make
g++ -c test.cpp
test.cpp:31:35: fatal error: naza_interface_manual.h: No such file or
directory
#include "naza_interface_manual.h"
^
compilation terminated.
Makefile:5: recipe for target 'test.o' failed
make: *** [test.o] Error 1
The Makefile for test.cpp looks like that:
output: test.o
g++ -L. -lnazainterface -o test test.o
test.o:
g++ -c test.cpp
clean:
rm -f *.o
test.cpp just includes the library.
#include "naza_interface_manual.h"
The library contains two files, naza_interface_manual.h and naza_interface_manual.cpp. The library's makefile looks like that:
libso: naza_interface_manual.o pca9685.o
g++ -fPIC -L/usr/local/lib -shared naza_interface_manual.o
pca9685.o -lbcm2835 -o libnazainterface.so
naza_interface_manual.o: src/naza_interface_manual.cpp src/naza_interface_manual.h
g++ -fPIC -c -Wall src/naza_interface_manual.cpp
pca9685.o: src/PCA9685/pca9685.cpp src/PCA9685/pca9685.h
g++ -c src/PCA9685/pca9685.cpp
install: naza_interface_manual.o pca9685.o
g++ -L/usr/local/lib naza_interface_manual.o pca9685.o -lbcm2835 -
shared -o /usr/local/libnazainterface.so
clean:
rm *.o output
naza_interface_manual.h:
#ifndef NAZA_INTERFACE_MANUAL_H_
#define NAZA_INTERFACE_MANUAL_H_
class naza_interface_manual_c{
public:
naza_interface_manual_c();
// A: For roll control (left/right)
// E: For pitch control (front/back)
// T: For throttle control
// R: For rudder control
// U: For Control Model Switch
void configure_pins(int A, int E, int T, int R, int U);
void fly_forward(int speed);
void fly_backward(int speed);
void fly_up(int speed);
void fly_down(int speed);
void fly_left(int speed);
void fly_right(int speed);
};
#endif
naza_interface_manual.cpp:
#include <iostream>
#include <wiringPi.h>
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include "naza_interface_manual.h"
#include "PCA9685/pca9685.h"
naza_interface_manual_c::naza_interface_manual_c(){
std::cout << "Starting Naza Interface";
}
void naza_interface_manual_c::configure_pins(int A, int E, int T, int R, int U){
PCA9685 pca9685;
pca9685.SetFrequency(100);
pca9685.Write(CHANNEL(0), VALUE(350));
}
void naza_interface_manual_c::fly_forward(int speed){
}
void naza_interface_manual_c::fly_backward(int speed){
}
void naza_interface_manual_c::fly_up(int speed){
}
void naza_interface_manual_c::fly_down(int speed){
}
void naza_interface_manual_c::fly_left(int speed){
}
void naza_interface_manual_c::fly_right(int speed){
}
Your Makefile doesn't install the header file. In fact, it also installs the shared object in a non-standard location: /usr/local. You want the library to go into /usr/local/lib and you need the header file installed in /usr/local/include.
Your Makefile is not consistent with conventional rules: You have no all rule, you are creating the library directly in the installation directory, instead of calling /usr/bin/install... I suggest you look into "proper" Makefile layout, if you want to distribute this. Users expect a lot of things from the Makefiles you give them; there are de-facto standards to follow.
If you want to use the library without having installed it, you need to provide the compiler the relevant include directive in your test.o: target; something like -Ipath/to/your/header.
Your compilation doesn't give the compiler the include path to find the header.
Instead, specify a base location and add the path to the compile. Otherwise if you can change the naza interface library, its install target should install the headers to a system (or $PREFIX/include) location.
test.o:
g++ -I$(NAZA_INTERFACE_LIB)/src/ -c test.cpp
Related
I have to create a Library for my work that contains Protobuf elements. It should run on every other PC without installing Protobuf. But I can not make the library run without having also the Protobuf files in the same folder (so I compile this files to and the user have to install Protobuf)
So I created for this a test program to demonstrate my problem:
->alias.proto
syntax = "proto3";
package aliasPackage;
message NumberSave{
int32 number = 1;
}
I created the .h and .cc with
protoc -I. --cpp_out=. alias.proto
->Backbone.h
#include "alias.pb.h"
class Backbone{
public:
Backbone();
~Backbone();
void save_Number(int value);
int get_Number();
private:
aliasPackage::NumberSave number;
};
->Backbone.cpp
#include "../header/Backbone.h"
#include <google/protobuf/stubs/common.h>
Backbone::Backbone()
{
number.set_number(0);
}
Backbone::~Backbone()
{
google::protobuf::ShutdownProtobufLibrary();
}
void Backbone::save_Number(int value)
{
number.set_number(value);
}
int Backbone::get_Number()
{
return number.number();
}
->Backbone.h for the lib
class Backbone{
public:
Backbone();
~Backbone();
void save_Number(int value);
int get_Number();
};
Creating the lib out of the files with this command (I thought about a static one, compiling the all independences into the file, but it seems not to work)
g++ -c --std=c++20 -O3 -DBUILD_SHARED_LIBS=ON -I/usr/local/include *.c* -lpthread -L/usr/local/lib -lprotobuf && ar rcs Backbone.sll *.o
->main.cpp
#include "../libs/lib/Backbone.h"
#include <iostream>
int main(){
auto backbone = new Backbone();
backbone->save_Number(5);
std::cout<<backbone->get_Number()<<std::endl;
delete backbone;
return 0;
}
Compile command
g++ -Wall -Wextra -Wpedantic --std=c++20 -O3 main.cpp -L. -l:../libs/lib/Backbone.sll
What am I doing wrong? What's the right command to create a Lib so that users can use it without installing Protobuf?
I write simple testing program in C++, which will tell Hello, Alex and exit.
Here it's code:
main.cpp:
#include <iostream>
#include <dlfcn.h>
int main()
{
void* descriptor = dlopen("dll.so", RTLD_LAZY);
std::string (*fun)(const std::string name) = (std::string (*)(const std::string)) dlsym(descriptor, "sayHello");
std::cout << fun("Alex") << std::endl;
dlclose(descriptor);
return 0;
}
dll.h:
#ifndef UNTITLED_DLL_H
#define UNTITLED_DLL_H
#include <string>
std::string sayHello(const std::string name);
#endif
dll.cpp:
#include "dll.h"
std::string sayHello(const std::string name)
{
return ("Hello, " + name);
}
makefile:
build_all : main dll.so
main : main.cpp
$(CXX) -c main.cpp
$(CXX) -o main main.o -ldl
dll.so : dll.h dll.cpp
$(CXX) -c dll.cpp
$(CXX) -shared -o dll dll.o
But when I build my code with make, I have such error:
/usr/bin/ld: dll.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
dll.o: error adding symbols: Bad value
collect2: error: ld returned 1 exit status
makefile:8: recipe for target 'dll.so' failed
make: *** [dll.so] Error 1
What did I make not correct?
P.S. I use GNU Make 3.81 on Ubuntu Server 14.04.3 with GNU GCC 4.8.4
Update
If I link dll.so file with -fPIC param, I have the same error
Firstly, a bit off topic, but in your makefile, it would be better to specify build_all as a phony target
.PHONY: build_all
Next, you are compiling dll.cpp without relocatable code. You need to add -fpic or -fPIC (see here for an explanation of the difference).
$(CXX) -c dll.cpp -fpic
Lastly, unix doesn't automatically add file suffixes, so here you need to specify .so:
$(CXX) -shared -o dll.so dll.o
I want to have the functions which are defined in another .cpp file become available in another simulation tool.
I found the following code in this question: -finstrument-functions doesn't work with dynamically loaded g++ shared objects (.so)
Trace.cpp
#include <stdio.h>
#ifdef __cplusplus
extern "C"
{
void __cyg_profile_func_enter(void *this_fn, void *call_site)
__attribute__((no_instrument_function));
void __cyg_profile_func_exit(void *this_fn, void *call_site)
__attribute__((no_instrument_function));
}
#endif
void __cyg_profile_func_enter(void* this_fn, void* call_site)
{
printf("entering %p\n", (int*)this_fn);
}
void __cyg_profile_func_exit(void* this_fn, void* call_site)
{
printf("exiting %p\n", (int*)this_fn);
}
Trace.cpp is compiled by doing:
g++ -g -finstrument-functions -Wall -Wl,-soname,libMyLib.so.0 -shared -fPIC -rdynamic MyLib.cpp MyLibStub.cpp Trace.cpp -o libMyLib.so.0.0
ln -s libMyLib.so.0.0 libMyLib.so.0
ln -s libMyLib.so.0.0 libMyLib.so
g++ MainStatic.cpp -g -Wall -lMyLib -L./ -o MainStatic
g++ MainDynamic.cpp -g -Wall -ldl -o MainDynamic
Note that I don't need: MyLib.cpp and MyLibStub.cpp.
Instead compiled Trace.cpp doing:
g++ -g -finstrument-functions -Wall -Wl,-soname,libMyLib.so.0 -shared -fPIC -rdynamic Trace.cpp -o libMyLib.so.0.0
What I've tried:
The shared object where I want to have Trace.cpp is obtained by:
opp_makemake -f --deep --no-deep-includes --make-so -I . -o veins -O out -I../../inet/src/util/headerserializers/sctp/headers -L../../inet/src -linet
I added -L and -l:
opp_makemake -f --deep --no-deep-includes --make-so -I . -o veins -L /home/user/Desktop/test/ -lMyLib -O out -I../../inet/src/util/headerserializers/sctp/headers -L../../inet/src -linet
and got:
/usr/bin/ld: cannot find -lMyLib
I also tried:
opp_makemake -f --deep --no-deep-includes --make-so -I . -o veins /home/user/Desktop/test/libMyLib.so.0.0 -O out -I../../inet/src/util/headerserializers/sctp/headers -L../../inet/src -linet
which compiled successfully but the application crashed:
Error during startup: Cannot load library
'../../src//libveins.so': libMyLib.so.0: cannot open shared object
file: No such file or directory.
Question:
How to compile Trace.cpp correctly?
How to link it with the rest of the shared library?
As you might notice I am not very experienced with compiling, linking and similar. So, any extra explanation is very welcome!
As #Flexo restates what #EmployedRussian said in the linked question, the main point is to get your implementation of __cyg_profile_func_*** before the one provided by libc.so.6.
One method to do this, is to use the LD_PRELOAD environment variable. Here you can read what LD_PRELOAD does and how it works.
To use the LD_PRELOAD trick you will need to compile your implementation of the above-mentioned functions as a shared library.
You can do this by doing:
g++ -shared -fPIC myImp.cc -o myImp.so -ldl
Once you get the .so file, navigate to the directory where your executable is located and do:
LD_PRELOAD=<path/to/myImp.so>- ./<myExecutable>
For shared libraries, dynamic linking is used. Meaning:
resolving of some undefined symbols (is postponed) until a program is run.
By using LD_PRELOAD you resolve the symbols of your interest before letting the linked do that.
Here you have an implementation of myImp.cc, which I took from: https://groups.google.com/forum/#!topic/gnu.gcc.help/a-hvguqe10I
The current version lacks proper implementation for __cyg_profile_func_exit, and I have not been able to demangle the function names.
#ifdef __cplusplus
extern "C"
{
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dlfcn.h>
void __cyg_profile_func_enter(void *this_fn, void *call_site)__attribute__((no_instrument_function));
void __cyg_profile_func_exit(void *this_fn, void *call_site)__attribute__((no_instrument_function));
}
#endif
static FILE *fp;
int call_level=0;
void * last_fn;
void __cyg_profile_func_enter(void *this_fn, void *call_site)
{
Dl_info di;
if (fp == NULL) fp = fopen( "trace.txt", "w" );
if (fp == NULL) exit(-1);
if ( this_fn!=last_fn) ++call_level;
for (int i=0;i<=call_level;i++)
{
fprintf(fp,"\t");
}
//fprintf(fp, "entering %p\n", (int *)this_fn);
fprintf(fp, "entering %p", (int *)this_fn);
if (dladdr(this_fn, &di)) {
fprintf(fp, " %s (%s)", di.dli_sname ? di.dli_sname : "<unknown>", di.dli_fname);
}
fputs("\n", fp);
(void)call_site;
last_fn = this_fn;
}
void __cyg_profile_func_exit(void *this_fn, void *call_site)
{
--call_level;
for (int i=0;i<=call_level;i++) fprintf(fp,"\t");
fprintf(fp, "exiting %p\n", (int *)this_fn);
(void)call_site;
}
Another option for function tracing which uses LD_PRELOAD is used by LTTng, in the section Function Tracing, but I have never used it...
I have an existing application that uses a C++ class, a C++ wrapper, and FORTRAN code for the computationally intensive parts of the application. I would like to implement parts of the FORTRAN in CUDA to take advantage of parallelization, but I would still like to access some of the subroutines, so I need to link CUDA, C++, and FORTRAN code.
I have three questions:
1. How do I correctly link all of the object files with the Linux Terminal and with the Makefile (included below)?
2. What is the proper way to reference the CUDA function in the class header without confusing the compiler's recognition of device and host code?
3. Is passing a class to CUDA just like passing a class to any other external C code?
Note: I have not included full code (some of it is quite long) except for the Makefile. If I need to include more, please let me know.
.h file
#ifndef _DGCPM_H_
#define _DGCPM_H_
extern "C"{
#include <string.h>
#include <zlib.h>
#include <math.h>
}
/* Prototypes of Fortran subroutines */
extern "C" {
void initialize_(float *2Darray);
void advance_(float *2Darray);
//Want "advance" to be implemented in CUDA
}
/* Proper prototype of CUDA call? */
//extern "C" void cudaadvance(float *2Darray);
class DGCPM{
public:
DGCPM(); /* Initialized with defaults setup */
~DGCPM(); /* Free memory */
void advance(float dT); /* Advance model dT seconds */
private:
float **2Darray;
void initialize(float **2Darray);
};
#endif
.C wrapper
#include "../include/DGCPM.h"
DGCPM::DGCPM(){
initialize();
}
void DGCPM::advance(float dT){
advance_(2Darray[0]);
}
main.C file
#include <stdlib.h>
#include <stdio.h>
#include <zlib.h>
#include "../include/DGCPM.h"
int main(){
class DGCPM *model;
model=new class DGCPM();
//Write data to class from a file, then
for(int i=0;i<200;i++){
printf("%d\n",i);
model->advance(3600);
//write model state to file;
}
//Close file
return 0;
}
Makefile (Note: "pbo" is the FORTRAN code)
INSTALLDIR=../../lib/
FLAGS=-Wall -g -I ../../amj/include
CFLAGS=$(FLAGS)
CPPFLAGS=$(FLAGS)
FFLAGS=$(FLAGS)
CPP=g++
CC=gcc
FC=g77
PBO_PATH=../ober/for/
VPATH=$(PBO_PATH)
DGCPM_OBJ=DGCPM.o pbo.o
TESTDGCPM_OBJ=testDGCPM.o DGCPM.o pbo.o
ALL_OBJ=$(TESTDGCPM_OBJ)
install: all
mkdir -p $(INSTALLDIR)
cp libDGCPM.a $(INSTALLDIR)
all: libDGCPM.a testDGCPM
libDGCPM.a: $(DGCPM_OBJ)
ar rc $# $^
testDGCPM: $(TESTDGCPM_OBJ)
$(CPP) -o $# $^ -L ../../amj/lib -lamjMemory -lg2c -lz
clean:
- rm $(ALL_OBJ)
- rm $(INSTALLDIR)/libDGCPM.a
You currently don't have any CUDA code, so I may can't give enough details.
For your Qs:
Linking object files including CUDA code requires nvcc compiler driver. You could first compile your code files with individual compilers, i.e. gcc for .c, g++ for .cpp, g77 for .f and nvcc for .cu. Then you can use nvcc to link all the object files .o;
host and device code are explicitly declared in .cu file with __host__ and __device__. It's your responsibility not to invoke device code from other host code;
Why are your passing a class to CUDA? If you want to replace your fortran code with CUDA, you only need to invoke CUDA functions in your C++ wrapper class, and invoking CUDA API functions uses the the same grammar as invoking c++ functions.
Here is an example from my project. The executable is built with 1 .cu, 1 .cpp, a few extern .a as well as some .so. For .cpp I use Intel's compiler icpc other than the default g++. Please note my main() is in the .cu file.
# Compile : bin.cu/b-rbm-gpu.cu
nvcc -ftz true -ccbin icpc -Xcompiler "-Wall -Wno-long-long -ansi -pedantic -ansi-alias -parallel -fopenmp -openmp-link=static -static-intel -wd10237" -O3 -Xcompiler "-O3" -gencode arch=compute_20,code=sm_20 -Ilib -c -o bin.cu/b-rbm-gpu.o bin.cu/b-rbm-gpu.cu
# Compile : lib/KTiming.cpp
icpc -Wall -Wno-long-long -ansi -pedantic -ansi-alias -parallel -fopenmp -openmp-link=static -static-intel -wd10237 -O3 -MMD -Ilib -c -o lib/KTiming.o lib/KTiming.cpp
# Link : bin.cu/b-rbm-gpu
nvcc -ftz true -ccbin icpc -Xcompiler "-Wall -Wno-long-long -ansi -pedantic -ansi-alias -parallel -fopenmp -openmp-link=static -static-intel -wd10237" -O3 -Xcompiler "-O3" -Ilib -Llib bin.cu/b-rbm-gpu.o lib/KTiming.o -lpthread -lm /opt/intel/composer_xe_2013.1.117/mkl/lib/intel64/libmkl_intel_lp64.a /opt/intel/composer_xe_2013.1.117/mkl/lib/intel64/libmkl_intel_thread.a /opt/intel/composer_xe_2013.1.117/mkl/lib/intel64/libmkl_core.a /opt/intel/composer_xe_2013.1.117/mkl/lib/intel64/libmkl_core.a -lcublas -lcurand -lcusparse -o bin.cu/b-rbm-gpu
Here is the solution. To use the CUDA code, I reference it with, for example,
extern "C" void myfunction_(void)
In the header file, I add
void myfunction_(void);
in the extern "C" prototypes. In the public functions of the class I added
void mycudafunction(void);
In the C++ wrapper, I add
void DGCPM::mycudafunction(){
myfunction_();
}
I can now call "myfunction" from the main program with this type of syntax
model = new class DGCPM();
model->mycudafunction();
I modified my Makefile by adding myfunction.o to all of my objects and adding
-L /usr/local/cuda/lib -lcuda -lcudart
to all of my linking instructions.
To compile, create the CUDA object file (myfunction.o), and link, I type this in the terminal:
nvcc -c myfunction.cu
make
Here is the modified code:
.h file
#ifndef _DGCPM_H_
#define _DGCPM_H_
extern "C"{
#include <string.h>
#include <zlib.h>
#include <math.h>
}
/* Prototypes of Fortran subroutines */
extern "C" {
void initialize_(float *2Darray);
void advance_(float *2Darray);
/*CUDA prototype, can be changed to "cudaadvance" or the like*/
void myfunction_(void);
}
class DGCPM{
public:
DGCPM(); /* Initialized with defaults setup */
~DGCPM(); /* Free memory */
void advance(float dT); /* Advance model dT seconds */
void mycudafunction(void);
private:
float **2Darray;
void initialize(float **2Darray);
};
#endif
.C Wrapper
#include "../include/DGCPM.h"
DGCPM::DGCPM(){
initialize();
}
void DGCPM::advance(float dT){
advance_(2Darray[0]);
}
void DGCPM::mycudafunction(){
myfunction_();
}
main.C file
#include <stdlib.h>
#include <stdio.h>
#include <zlib.h>
#include "../include/DGCPM.h"
int main(){
class DGCPM *model;
model=new class DGCPM();
//Write data to class from a file, then
for(int i=0;i<200;i++){
printf("%d\n",i);
model->mycudafunction();
model->advance(3600);
//write model state to file;
}
//Close file
return 0;
}
Makefile
INSTALLDIR=../../lib/
FLAGS=-Wall -g -I ../../amj/include
CFLAGS=$(FLAGS)
CPPFLAGS=$(FLAGS)
FFLAGS=$(FLAGS)
CPP=g++
CC=gcc
FC=g77
PBO_PATH=../ober/for/
VPATH=$(PBO_PATH)
DGCPM_OBJ=DGCPM.o pbo.o myfunction.o
TESTDGCPM_OBJ=testDGCPM.o DGCPM.o pbo.o myfunction.o
ALL_OBJ=$(TESTDGCPM_OBJ)
install: all
mkdir -p $(INSTALLDIR)
cp libDGCPM.a $(INSTALLDIR)
all: libDGCPM.a testDGCPM
libDGCPM.a: $(DGCPM_OBJ)
ar rc $# $^
testDGCPM: $(TESTDGCPM_OBJ)
$(CPP) -o $# $^ -L ../../amj/lib -lamjMemory -lg2c -lz -L /usr/local/cuda/lib -lcuda -lcudart
clean:
- rm $(ALL_OBJ)
- rm $(INSTALLDIR)/libDGCPM.a
Here's the simple CUDA program I used to test.
#include <stdio.h>
__global__ void kernel( void ) {
}
extern "C" void myfunction_(void) {
kernel<<<1,1>>>();
printf( "Hello, World!\n" );
return;
}
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