undefined reference to 'myNamespace::MyClass::myFunc()' [duplicate] - c++

This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 7 years ago.
I am having a problem calling functions from my test_dll.dll in an outside c++ main. Working on eclipse cdt luna sr2 64, Windows 7. Using the MinGW toolchain for compilation.
The dll .cpp code :
#include <iostream>
#include "MyClass.h"
namespace myNamespace {
MyClass::MyClass() :a(1) {
std::cout << "MyClass():a(" << this->a << ")"<<std::endl;
}
MyClass::~MyClass() { }
void myFunc() {
std::cout << "myFunc() has been called !" << std::endl;
}
}
and it is compiled within eclipse with the following lines :
g++ -O0 -g3 -Wall -c -fmessage-length=0 -o MyClass.o "..\\MyClass.cpp"
g++ -shared -o libtest_dll.dll MyClass.o
My main code is the following :
#include <iostream>
#include "MyClass.h"
using namespace std;
int main() {
cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
myNamespace::MyClass *instance = new myNamespace::MyClass;
instance->myFunc();
return 0;
}
and it is compiled with the following
g++ "-IC:\\Users\\nxa02192\\Desktop\\MY_WORKSPACE\\test_dll" "-includeC:\\Users\\nxa02192\\Desktop\\MY_WORKSPACE\\test_dll\\MyClass.h" -O0 -g3 -Wall -c -fmessage-length=0 -o "src\\test_main.o" "..\\src\\test_main.cpp"
g++ "-LC:\\Users\\nxa02192\\Desktop\\MY_WORKSPACE\\test_dll\\Debug" -o test_main.exe "src\\test_main.o" -llibtest_dll
src\test_main.o: In function `main':
C:\Users\nxa02192\Desktop\MY_WORKSPACE\test_main\Debug/../src/test_main.cpp:20: undefined reference to `myNamespace::MyClass::myFunc()'
collect2.exe: error: ld returned 1 exit status
However, what i don't get is that if i just instanciate the class, it will output the correct a=1 value, as specified in the constructor.
I already specified the include paths to the compiler and the library path and file to the linker, as you can see in the compiling commands. Any Ideas ? Thanks !

Change
void myFunc() {
std::cout << "myFunc() has been called !" << std::endl;
}
to
void MyClass::myFunc() {
std::cout << "myFunc() has been called !" << std::endl;
}

Related

Issue with std::thread from c++11

I have some troubles trying to compile a program with multi-threading from the standard template library.
It return me a obscure error when i try to compile the following program :
#include <iostream>
#include <thread>
void foo()
{
std::cout << "Thread 1\n";
}
int main(int argc, char** argv)
{
std::thread tr(foo);
std::cout << "Main thread\n";
tr.join();
return 0;
}
I don't understand the error :
/tmp/ccE8EtL1.o : In the function « std::thread::thread<void (&)()>(void (&)()) » :
file.cpp:(.text._ZNSt6threadC2IRFvvEJEEEOT_DpOT0_[_ZNSt6threadC5IRFvvEJEEEOT_DpOT0_]+0x21) : undefined reference to « pthread_create »
collect2: error : ld has return 1 execution status code
I compile it with :
g++ -std=c++14 file.cpp -o test -Wall
Can anyone help me please ?
Pass -pthread to the compiler. This flag combines what is necessary to compile and link the pthread library (-lpthread is not always enough). See this question.

g++ link error: 'undefined reference to 'main'

I have 3 files; main.cpp (which contains main()), FileWriter.h, and FileWriter.cpp. I'm using g++ (version Debian 4.9.2-10) on Debian Jessie. My project contains .cpp files in '/root/dev/Practice/src/', and a single header (FileWriter.h) in '/root/dev/Practice/include/'. The compilation of the two object files works, but the linking to an executable complains about undefined reference to main(), although I do indeed have a seemingly valid one defined in 'main.cpp'.
Here's the output of my make file (which is in the root '/root/dev/Practice/' directory):
g++ -c -g -Wall -o src/FileWriter.o src/FileWriter.cpp
g++ -c -g -Wall -o src/main.o src/FileWriter.cpp
g++ src/FileWriter.o src/main.o -o bin/Practice
/usr/lib/gcc/i586-linux-gnu/4.9/../../../i386-linux-gnu/crt1.o: In function '_start'"
/build/glibc-J1NNmk/glibc-2.19/csu/../sysdeps/i386/start.S:111: undefined reference to 'main'
collect2: error: ls returned 1 exit status
Makefile:10: recipe for target 'bin/Practice' failed
Here's the contents of my main.cpp file:
#include <string>
#include <iostream>
#include "/root/dev/Practice/include/FileWriter.h"
int main() {
std::cout << "Hello!" << std::endl;
FileWriter * fw = new FileWriter("foofile");
fw->AddLine("CRAP!");
fw->AddLine("NO!");
return 0;
}
My FileWriter.h:
#ifndef FILEWRITER_H_
#define FILEWRITER_H_
#include <string>
#include <iostream>
class FileWriter{
public:
FileWriter(std::string);
~FileWriter();
void AddLine(std::string);
private:
std::string fileLocation;
std::ofstream *filestream;
};
#endif /* FILEWRITER_H_ */
...and my FileWriter.cpp:
#include "/root/dev/Practice/include/FileWriter.h"
#include <fstream>
// g++ linker error if 'inline' not included - why?
inline FileWriter::FileWriter(std::string fileName)
{
this->fileLocation = fileName;
const char * x = this->fileLocation.c_str();
this->filestream = new std::ofstream();
this->filestream->open(x, std::ios::out | std::ios::app);
}
inline FileWriter::~FileWriter()
{
this->filestream->close();
}
inline void FileWriter::AddLine(std::string line)
{
*this->filestream << line << std::endl;
}
This line:
g++ -c -g -Wall -o src/main.o src/FileWriter.cpp
should be:
g++ -c -g -Wall -o src/main.o src/main.cpp
I don't have access to this compiler, but in the past if you had main() in a C++ file you needed to "decorate" it with __cdecl
int __cdecl main() {
Try that? Or:
extern "C" int main() {

codeblocks c++ error: undefined reference to 'subclass::subclass()' [duplicate]

I can't seem to get the errors to go away. The errors are below. I have looked on Google Search and still I can't figure it out. It is not like I am new to C++, but I have not fooled around with it in a while.
The weird thing is it worked with g++ on Windows...
Errors using:
g++ main.cpp
Output:
/tmp/ccJL2ZHE.o: In function main': \ main.cpp:(.text+0x11): undefined reference to Help::Help()'
main.cpp:(.text+0x1d): undefined reference to Help::sayName()' \ main.cpp:(.text+0x2e): undefined reference to Help::~Help()'
main.cpp:(.text+0x46): undefined reference to `Help::~Help()'
collect2: ld returned 1 exit status
File main.cpp
#include <iostream>
#include "Help.h"
using namespace std;
int main () {
Help h;
h.sayName();
// ***
// ***
// ***
return 0;
}
File Help.h
#ifndef HELP_H
#define HELP_H
class Help {
public:
Help();
~Help();
void sayName();
protected:
private:
};
#endif // HELP_H
File Help.cpp
#include <iostream>
#include "Help.h"
using namespace std;
Help::Help() { // Constructor
}
Help::~Help() { // Destructor
}
void Help::sayName() {
cout << " ***************" << endl;
cout << " ************************************" << endl;
cout << " ************" << endl;
cout << " *********************" << endl;
}
Use
g++ main.cpp Help.cpp
You have to tell the compiler all the files that you want it to compile, not just the first one.
You should add help.o to your g++ line:
g++ -c help.cpp -o help.o
g++ help.o main.cpp
By splitting it to two lines you can save compilation time (in case of larger projects), because you can compile help.cpp only when it was changed. make and Makefile used well will save you a lot of headache:
#Makefile
all: main
main: help main.cpp
g++ -o main help.o main.cpp
help: help.cpp
g++ -c -o help.o help.cpp
I had the same problem with my Linux Lubuntu distribution and it was creating the problem for my constructor and destructor. It was not recognizing them.
Actually, this goes off if you just compile all of the three files together. So, once you saved all your files, just do this:
g++ main.cpp Help.h Help.cpp
./a.out
./a.out is the executable file for the Linux. Sorry, but I don't know about the Windows. And your program would run smoothly.

How to pass arguments to a method loaded from a static library in CPP

I'm trying to write a program to use a static library of a C++ code into another C++ code. The first C++ code is hello.cpp:
#include <iostream>
#include <string.h>
using namespace std;
extern "C" void say_hello(const char* name) {
cout << "Hello " << name << "!\n";
}
int main(){
return 0;
}
The I made a static library from this code, hello.a, using this command:
g++ -o hello.a -static -fPIC hello.cpp -ldl
Here's the second C++ code to use the library, say_hello.cpp:
#include <iostream>
#include <string>
#include <dlfcn.h>
using namespace std;
int main(){
void* handle = dlopen("./hello.a", RTLD_LAZY);
cout<<handle<<"\n";
if (!handle) {
cerr<<"Cannot open library: "<<dlerror()<<'\n';
return 1;
}
typedef void (*hello_t)();
dlerror(); // reset errors
hello_t say_hello = (hello_t) dlsym(handle, "say_hello");
const char *dlsym_error = dlerror();
if (dlsym_error) {
cerr<<"Cannot load symbol 'say_hello': "<<dlsym_error<<'\n';
dlclose(handle);
return 1;
}
say_hello("World");
dlclose(handle);
return 0;
}
Then I compiled say_hello.cpp using:
g++ -W -ldl say_hello.cpp -o say_hello
and ran ./say_hello in the command line. I expected to get Hello World! as output, but I got this instead:
0x8ea4020
Hello ▒▒▒▒!
What is the problem? Is there any trick to make compatibility for method's argument like what we use in ctypes or what?
If it helps I use a lenny.
EDIT 1:
I have changed the code and used a dynamic library, 'hello.so', which I've created using this command:
g++ -o hello.so -shared -fPIC hello.cpp -ldl
The 6th line of the code changed to:
void* handle = dlopen("./hello.so", RTLD_LAZY);
When I tried to compile say_hello.cpp, I got this error:
say_hello.cpp: In function ‘int main()’:
say_hello.cpp:21: error: too many arguments to function
I also tried to compile it using this line:
g++ -Wall -rdynamic say_hello.cpp -ldl -o say_hello
But same error raised. So I removed the argument "World" and the it has been compiled with no error; but when I run the executable, I get the same output like I have mentioned before.
EDIT 2:
Based on #Basile Starynkevitch 's suggestions, I changed my say_hello.cpp code to this:
#include <iostream>
#include <string>
#include <dlfcn.h>
using namespace std;
int main(){
void* handle = dlopen("./hello.so", RTLD_LAZY);
cout<<handle<<"\n";
if (!handle) {
cerr<<"Cannot open library: "<<dlerror()<<'\n';
return 1;
}
typedef void hello_sig(const char *);
void* hello_ad = dlsym(handle, "say_hello");
if (!hello_ad){
cerr<<"dlsym failed:"<<dlerror()<<endl;
return 1;
}
hello_sig* fun = reinterpret_cast<hello_sig*>(hello_ad);
fun("from main");
fun = NULL;
hello_ad = NULL;
dlclose(handle);
return 0;
}
Before that, I used below line to make a .so file:
g++ -Wall -fPIC -g -shared hello.cpp -o hello.so
Then I compiled say_hello.cpp wth this command:
g++ -Wall -rdynamic -g say_hello.cc -ldl -o say_hello
And then ran it using ./say_hello. Now everything is going right. Thanks to #Basile Starynkevitch for being patient about my problem.
Functions never have null addresses, so dlsym on a function name (or actually on any name defined in C++ or C) cannot be NULL without failing:
hello_t say_hello = (hello_t) dlsym(handle, "say_hello");
if (!say_hello) {
cerr<<"Cannot load symbol 'say_hello': "<<dlerror()<<endl;
exit(EXIT_FAILURE);
};
And dlopen(3) is documented to dynamically load only dynamic libraries (not static ones!). This implies shared objects (*.so) in ELF format. Read Drepper's paper How To Use Shared Libraries
I believe you might have found a bug in dlopen (see also its POSIX dlopen specification); it should fail for a static library hello.a; it is always used on position independent shared libraries (like hello.so).
You should dlopen only position independent code shared objects compiled with
g++ -Wall -O -shared -fPIC hello.cpp -o hello.so
or if you have several C++ source files:
g++ -Wall -O -fPIC src1.cc -c -o src1.pic.o
g++ -Wall -O -fPIC src2.cc -c -o src2.pic.o
g++ -shared src1.pic.o src2.pic.o -o yourdynlib.so
you could remove the -O optimization flag or add -g for debugging or replace it with -O2 if you want.
and this works extremely well: my MELT project (a domain specific language to extend GCC) is using this a lot (generating C++ code, forking a compilation like above on the fly, then dlopen-ing the resulting shared object). And my manydl.c example demonstrates that you can dlopen a big lot of (different) shared objects on Linux (typically millions, and hundred of thousands at least). Actually the limitation is the address space.
BTW, you should not dlopen something having a main function, since main is by definition defined in the main program calling (perhaps indirectly) dlopen.
Also, order of arguments to g++ matters a lot; you should compile the main program with
g++ -Wall -rdynamic say_hello.cpp -ldl -o say_hello
The -rdynamic flag is required to let the loaded plugin (hello.so) call functions from inside your say_hello program.
For debugging purposes always pass -Wall -g to g++ above.
BTW, you could in principle dlopen a shared object which don't have PIC (i.e. was not compiled with -fPIC); but it is much better to dlopen some PIC shared object.
Read also the Program Library HowTo and the C++ dlopen mini-howto (because of name mangling).
example
File helloshared.cc (my tiny plugin source code in C++) is
#include <iostream>
#include <string.h>
using namespace std;
extern "C" void say_hello(const char* name) {
cout << __FILE__ << ":" << __LINE__ << " hello "
<< name << "!" << endl;
}
and I am compiling it with:
g++ -Wall -fPIC -g -shared helloshared.cc -o hello.so
The main program is in file mainhello.cc :
#include <iostream>
#include <string>
#include <dlfcn.h>
#include <stdlib.h>
using namespace std;
int main() {
cout << __FILE__ << ":" << __LINE__ << " starting." << endl;
void* handle = dlopen("./hello.so", RTLD_LAZY);
if (!handle) {
cerr << "dlopen failed:" << dlerror() << endl;
exit(EXIT_FAILURE);
};
// signature of loaded function
typedef void hello_sig_t(const char*);
void* hello_ad = dlsym(handle,"say_hello");
if (!hello_ad) {
cerr << "dlsym failed:" << dlerror() << endl;
exit(EXIT_FAILURE);
}
hello_sig_t* fun = reinterpret_cast<hello_sig_t*>(hello_ad);
fun("from main");
fun = NULL; hello_ad = NULL;
dlclose(handle);
cout << __FILE__ << ":" << __LINE__ << " ended." << endl;
return 0;
}
which I compile with
g++ -Wall -rdynamic -g mainhello.cc -ldl -o mainhello
Then I am running ./mainhello with the expected output:
mainhello.cc:7 starting.
helloshared.cc:5 hello from main!
mainhello.cc:24 ended.
Please notice that the signature hello_sig_t in mainhello.cc should be compatible (homomorphic, i.e. the same as) with the function say_hello of the helloshared.cc plugin, otherwise it is undefined behavior (and you probably would have a SIGSEGV crash).

"undefined reference to" using 'g++' to compile a C++ program

I can't seem to get the errors to go away. The errors are below. I have looked on Google Search and still I can't figure it out. It is not like I am new to C++, but I have not fooled around with it in a while.
The weird thing is it worked with g++ on Windows...
Errors using:
g++ main.cpp
Output:
/tmp/ccJL2ZHE.o: In function main': \ main.cpp:(.text+0x11): undefined reference to Help::Help()'
main.cpp:(.text+0x1d): undefined reference to Help::sayName()' \ main.cpp:(.text+0x2e): undefined reference to Help::~Help()'
main.cpp:(.text+0x46): undefined reference to `Help::~Help()'
collect2: ld returned 1 exit status
File main.cpp
#include <iostream>
#include "Help.h"
using namespace std;
int main () {
Help h;
h.sayName();
// ***
// ***
// ***
return 0;
}
File Help.h
#ifndef HELP_H
#define HELP_H
class Help {
public:
Help();
~Help();
void sayName();
protected:
private:
};
#endif // HELP_H
File Help.cpp
#include <iostream>
#include "Help.h"
using namespace std;
Help::Help() { // Constructor
}
Help::~Help() { // Destructor
}
void Help::sayName() {
cout << " ***************" << endl;
cout << " ************************************" << endl;
cout << " ************" << endl;
cout << " *********************" << endl;
}
Use
g++ main.cpp Help.cpp
You have to tell the compiler all the files that you want it to compile, not just the first one.
You should add help.o to your g++ line:
g++ -c help.cpp -o help.o
g++ help.o main.cpp
By splitting it to two lines you can save compilation time (in case of larger projects), because you can compile help.cpp only when it was changed. make and Makefile used well will save you a lot of headache:
#Makefile
all: main
main: help main.cpp
g++ -o main help.o main.cpp
help: help.cpp
g++ -c -o help.o help.cpp
I had the same problem with my Linux Lubuntu distribution and it was creating the problem for my constructor and destructor. It was not recognizing them.
Actually, this goes off if you just compile all of the three files together. So, once you saved all your files, just do this:
g++ main.cpp Help.h Help.cpp
./a.out
./a.out is the executable file for the Linux. Sorry, but I don't know about the Windows. And your program would run smoothly.