I have a static method in class as follows in file Convert.h
class Convert
{
public :
static string convertIntToStr(unsigned int integer);
};
In Convert.cpp
string
Convert::convertIntToStr(unsigned int integer)
{
ostringstream ostr;
ostr << integer;
return ostr.str();
}
I use this in some other class method in another .cpp file as Convert::convertIntToStr, but I get linking error, which says undefined reference to Convert::convertIntToStr(unsigned int). Could you please let me know what could be wrong?
With multiple cpp file, you have to link the compiled object file into executable. In IDE like eclipse CDT or Visual stdio, It has been done for you.
To compile and link by yourself, with gcc for example, write Makefile:
CC=g++
CPPFLAGS=-fPIC -Wall -g -O2
all:executable
executable: convert.o other.o
$(CC) $(CPPFLAGS) -o $# $^
convert.o: convert.cpp
$(RC) $^
other.o: other.cpp
$(CC) -o $# -c $^
.PHONY:clean
clean:
rm *.o executable
Related
To make this short, I have a CPP and C code, and my CPP code is trying to reference functions from the C code with a header file. Whenever I run the make command, I end up getting "undefined reference" errors. Here are my codes:
cpp_code.cpp:
extern "C"{
#include "header_code.h";
}
int main(){
cout << "Hello" << endl;
return 0;
}
c_code.c:
#include "header_code.h"
int main(){
printf("Hello");
return 0;
}
void initalize(){
printf("Initilized");
}
header_code.h:
extern void initalize();
makefile:
CXX = g++
CXXFLAGS = -std=c++11
CC = gcc
DEPS = header_code.h
CFLAGS = -I
OBJS = cpp_code.o c_code.o
c: $(OBJS)
$(CXX) -o $# $^ $(CXXFLAGS)
%.o : %.cpp
$(CXX) -c $(CXXFLAGS) $<
%.o : %.c $(DEPS)
$(CC) -c $(CFLAGS) $<
Whenever running make it always gives me problems. Can anyone please help me? Thank you for your time reading all of this!
[basic.start.main]
A program that declares a variable main at global scope, or that declares a function main at global scope attached to a named module, or that declares the name main with C language linkage (in any namespace) is ill-formed.
So, as a C++ program, it's ill-formed. Remove the C main function.
Other problems:
In the makefile you have
CFLAGS = -I
and whatever comes after that when compiling will be treated as a directory to search for header files in. In your makefile, that's the source file. Correction:
CFLAGS =
or
CFLAGS = -I.
Your header file is missing a header guard and header files that are supposed to be used by both C and C++ code usually contain the extern "C" part themselves to not burden C++ users to add it.
cpp_code.cpp
#include "header_code.h"
#include <iostream>
int main() {
initalize(); // call the C function
std::cout << "Hello" << std::endl;
}
c_code.c
#include "header_code.h"
#include <stdio.h>
void initalize(){
printf("Initilized");
}
header_code.h
#ifndef HEADER_CODE_H_
#define HEADER_CODE_H_
#ifdef __cplusplus
extern "C" {
#endif
extern void initalize();
#ifdef __cplusplus
}
#endif
#endif
makefile
CXX = g++
CXXFLAGS = -std=c++11
CC = gcc
DEPS = header_code.h
CFLAGS = -I.
OBJS = cpp_code.o c_code.o
c: $(OBJS)
$(CXX) -o $# $^ $(CXXFLAGS)
%.o : %.cpp
$(CXX) -c $(CXXFLAGS) $<
%.o : %.c $(DEPS)
$(CC) -c $(CFLAGS) $<
My C++ program consists of three files:
two source files 'main.cpp' and 'hellolib.cpp'
a header file 'hellolib.h'
I am creating a makefile for this program. For my assignment I need one target ('hello') that compiles all source files in an executable.
Another target ('obj') should compile all '.cpp' files into objects and link them together in an executable.
When running make I prefer the object files to be created in a seperate folder called 'bin'. The source files are would be in a folder called 'src'. These folders are siblings, the makefile is in it's parent folder.
My makefile works fine but I wish two combine the two targets 'bin/main.o' and 'bin/hellolib.o' into one to reduce the amount of rules, especially for later when I am dealing with more source files.
I imagined the replacement would look something like this, but it doesn't seem to work.
It gives me the error: "*** No rule ot make target 'bin/main.o',
needed by 'obj'. Stop.
bin/%.o : src/%.cpp
$(CC) -c $< -o $#
Working Makefile:
CC = g++
SOURCES = ./src/main.cpp \
./src/hellolib.cpp
OBJECTS = ./bin/main.o \
./bin/hellolib.o
hello : $(SOURCES)
$(CC) -o $# $^
obj : $(OBJECTS)
$(CC) -o $# $^
bin/main.o : src/main.cpp
$(CC) -c $< -o $#
bin/hellolib.o : src/hellolib.cpp
$(CC) -c $< -o $#
clean:
#rm -rf hello obj bin/*.o
main.cpp:
#include "hellolib.h"
int main() {
Hello h("Name");
h.Print();
return 0;
}
hellolib.cpp
#include "hellolib.h"
#include <iostream>
Hello::Hello(std::string name) {
if (name.empty()) {
cout << "Name is not valid!";
return;
}
_name = name;
}
void Hello::Print() {
cout << "Hello " << _name << endl;
}
hellolib.h
#ifndef HELLO_LIB_H
#define HELLO_LIB_H
#include <string>
using namespace std;
class Hello {
std::string _name;
public:
Hello(std::string name);
void Print();
};
#endif
You need to change:
OBJECTS = ./bin/main.o \
./bin/hellolib.o
to:
OBJECTS = bin/main.o \
bin/hellolib.o
(Removing leading "./"). Either that, or change your pattern rule to include the leading "./":
./bin/%.o : src/%.cpp
$(CC) -c $< -o $#
Make rule matching uses text matching. It's not based on filenames, so "./././foo" and "foo" are not the same thing.
Personally I recommend rewriting like this:
SOURCES = src/main.cpp \
src/hellolib.cpp
OBJECTS = $(patsubst src/%.cpp,bin/%.o,$(SOURCES))
so you only need to keep the list of files in one place.
You can make a rule that builds anything conforming to a specific pattern like this:
bin/%.o : src/%.cpp
$(CC) -c -o $# $<
That will compile any bin/%.o dependency from the corresponding source src/%.cpp.
Also it is standard when compiling C++ to use CXX rather than CC (which is for C code).
I'm new to C++, and I'm having some trouble setting up a simple class reference.
Class: Test.hh
#ifndef _TEST_HH_
#define _TEST_HH_
class Test {
public:
Test (double x);
};
#endif
Class Test.cc
#include "Test.hh"
#include <stdio.h>
Test::Test(double x) {
printf("%f",x);
}
Now I want to access this class from another class:
Class: DriverClass.hh
#ifndef _DRIVERCLASS_HH_
#define _DRIVERCLASS_HH_
#include "Test.hh"
class DriverClass {
public:
DriverClass(double y);
Test *t;
}
#endif
Class DriverClass.cc
#include "DriverClass.hh"
DriverClass::DriverClass(double y) {
t = new Test(y);
}
However, I get an error: "undefined reference to 'Test::Test(double)?
Does anyone know what might be wrong? Please assume that DriverClass is being called directly from a main method (not shown).
There is still an error in your post - a missing ; after the DriverClass
declaration. The rest is correct.
You should compile and link all the sources. The following is a sample Makefile and a
sample test code.
Makefile
all: t
t: t.cc DriverClass.cc Test.cc
g++ -Wall -g -o $# $^
clean:
rm -f *.o t
However, note that it's generally recommended to compile the sources into objects separately in order to compile only the sources changed after the last compilation. For example:
CFLAGS=-Wall -g
all: t
t: t.o DriverClass.o Test.o
g++ -o $# $^
t.o: t.cc DriverClass.o Test.o
g++ $(CFLAGS) -c $< -o $#
DriverClass.o: DriverClass.cc
g++ $(CFLAGS) -c $< -o $#
Test.o: Test.cc
g++ $(CFLAGS) -c $^ -o $#
clean:
rm -f *.o t
I've used the GNU compiler. For the meaning of $# and $^ variables refer to the official documentation.
t.cc
#include "Test.hh"
#include "DriverClass.hh"
int main(int argc, char const* argv[])
{
DriverClass d(10.4);
return 0;
}
Testing
$ make
g++ -Wall -g -o t t.cc DriverClass.cc Test.cc
$ ./t
10.400000
P.S.: don't forget to delete the allocated object.
I read different answers about VLA on SO but couldn't find the answer. In my case, I have one function that allocates memory:
template<typename T>
void allocMemory(T *&data, const size_t numElems)
{
#ifdef PINNED_MEMORY
// allocate pinned memory
#else
data = new T[numElems];
#endif
}
Now, I have a vector class where I use this method:
template<typename T>
class MyVec
{
T *data;
size_t size;
public:
MyVec(size_t _size): size(_size)
{ allocMemory<T>(data, size); } // gives VLA warning
};
It happens when I compile it using nvcc (V0.2.1221) compiler which I guess uses gcc compiler underneath (?) The actual warning is:
myvec.h:16:6: warning: ISO C++ does not support variable-length array types [-Wvla]
data = new T[numElems];
I think you don't compile your project the right way.
Try to using the flowing make file.
CUDA_INSTALL_PATH := /usr/local/cuda
CXX := g++
CC := gcc
LINK := g++ -fPIC
NVCC := nvcc
#Includes
INCLUDES = -I. -I$(CUDA_INSTALL_PATH)/include
#Common flags
COMMONFLAGS += $(INCLUDES)
NVCCFLAGS += $(COMMONFLAGS)
CXXFLAGS += $(COMMONFLAGS)
CFLAGS += $(COMMONFLAGS)
LIB_CUDA := -L$(CUDA_INSTALL_PATH)/lib -lcudart
#OBJS = GpuSolver.cu.o main.cpp.o
OBJS = main.cu.o a.cpp.o # your files
TARGET = a.out
LINKLINE = $(LINK) -o $(TARGET) $(OBJS) $(LIB_CUDA)
.SUFFIXES: .c .cpp .cu .o
%.c.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
.cu.o: %.cu
$(NVCC) $(NVCCFLAGS) -c $< -o $#
%.cpp.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $#
$(TARGET): $(OBJS) "makefile" #your makefile file name
$(LINKLINE)
I have a project using functions from a class CRandomMersenne, declared in header randomc.h; the functions are defined in a different file mersenne.cpp. In my makefile I have an object *MC_funcs2.o* that uses functions from the class. The source *MC_funcs2.cpp* includes the header randomc.h. However the compiler complains:
MC_funcs2.o:MC_funcs2.cpp:(.text+0x20): undefined reference to `CRandomMersenne::Random()'
I understand there is something I've done wrong with declaring functions outside the class definition, including header file to use mentioned functions and maybe with the linking in the makefile. Here is a stripped down version of some of the files:
makefile:
SpMC3: SpMC3.cpp SpMC.h mersenne.o MC_funcs2.o
g++ SpMC3.cpp MC_funcs2.o mersenne.o -o SpMC3
MC_funcs2.o: MC_funcs2.cpp SpMC.h randomc.h
g++ -c MC_funcs2.cpp mersenne.cpp
mersenne.o: mersenne.cpp randomc.h userintf.cpp
g++ -c mersenne.cpp userintf.cpp
SpMC3.cpp (main program):
#include "SpMC.h"
int main() {
cout << "boing" << endl;
return 0;
}
MCfuncs2.cpp (the one that doesn't compile):
#include "SpMC.h"
#include "randomc.h"
CRandomMersenne RanGen(time(0));
void outrandom() {
ofstream out;
out << RanGen.Random() << endl;
return;
}
Any ideas?
This error just means mersenne.cpp not being compiled ...make sure it get compiled and linked...
I would strongly advise compiling each individual source file *.c to a object file *.o, i.ex. mersenne.cpp -> mersenne.o. This can be achieved without having to specify each object file manually.
CC = gcc
CFLAGS = -g -O2
OBJECTS = main.o foo.o
main : $(OBJECTS)
$(CC) $(CFLAGS) $(OBJECTS) -o main
%.o : %.c
$(CC) $(CFLAGS) -c $<
For further information on makefiles, please take a look a this tutorial or excellent SO answer in How to make a SIMPLE C++ Makefile?.