D
dkarthik
Hello All,
I am a newbie to C++. I was trying a sample program from internet which
demonstrates dynamic class loading in C++. Actually, I thought of using
this design, in one of the applications I am working on.
However, the compilation was through. But when ran, the program
generated a SIGSEGV error. I debugged it using gdb and found that ,when
the symbol returned by dlsym() was invoked, the resulting value was
null.
I couldn't understand clearly why it didn't worked. The problematic
location in the code
has been denoted below(calc.cpp):
calc.cpp:
#include "calculator.hpp"
typedef Math* (*factory)(void);
bool Calculator::load(char* library_name) {
factory make;
/* Open shared library */
handle = dlopen(library_name, RTLD_NOW);
if (!handle) {
cout << dlerror();
return false;
}
/* Load symbols from library */
make = (factory)dlsym(handle, "maker");
if (make = NULL) {
cout << dlerror() << "\n";
return false;
}
/* Construct object */
math = (*make)(); ===> *** This is Problem location***
cout << (void*)math << "\n";
return true;
}
bool Calculator::calculate() {
float a;
cout << "Enter float:\n";
fscanf(stdin,"%f",&a);
c = math->square(a);
cout << "Square: " << c << '\n";
return true;
}
bool Calculator::close() {
char *error;
dlerror();
dlclose(handle);
if ((error = dlerror()) != NULL) {
cout << error;
return false;
}
return true;
}
main.cpp:
#include "calculator.hpp"
int main (int argc, char* argv[]) {
if (argc != 2)
cout << "Usage: calc \n";
Calculator* c = new Calculator();
if (c->load(argv[1])) {
c->calculate();
c->close();
}
delete c;
return 0;
}
calculator.hpp:
#ifndef __CALCULATOR_H
#define __CALCULATOR_H
#include "math.hpp"
class Calculator {
public:
bool load(char* library);
bool calculate();
bool close();
private:
void* handle;
Math* math;
};
#endif
math.hpp:
#ifndef __MATH_H
#define __MATH_H
class Math {
public:
virtual float multiply(float a, float b);
virtual float square(float a);
};
#endif
math.cpp:
#include "math.hpp"
float Math::multiply(float a, float b) {
return a*b;
}
float Math::square(float a) {
return a*a;
}
extern "C" {
Math *maker() {
return new Math;
}
}
I'm using g++ 3.2.3 and below is the makefile used to compile the
program.
LIB_SRC = math.cpp
LIB_OBJ = math.o
LIB = math
BIN_SRC = main.cpp calc.cpp
BIN = calc
LIB_VER_MAJOR =
LIB_VER_MINOR =
CC = g++
LIB_OBJ_FLAGS = -fPIC -c -Wall -g
LIB_SO_FLAGS = -shared -lc -Wl,-soname
BIN_FLAGS = -rdynamic -ldl -Wall -g
all: lib.o lib.so bin
lib.o:
$(CC) $(LIB_OBJ_FLAGS) $(LIB_SRC)
lib.so:
$(CC) $(LIB_SO_FLAGS),$(LIB).so.$(LIB_VER_MAJOR) \
-o $(LIB).so$(LIB_VER_MAJOR)$(LIB_VER_MINOR) $(LIB_OBJ)
bin:
$(CC) $(BIN_FLAGS) -o $(BIN) $(BIN_SRC)
clean:
rm -f *.o *.so* $(BIN)
Any pointers/suggestions to solve this problem will be really
appreciated. The argument to calc exe is math.so
Thanks & Regards,
Karthik D
I am a newbie to C++. I was trying a sample program from internet which
demonstrates dynamic class loading in C++. Actually, I thought of using
this design, in one of the applications I am working on.
However, the compilation was through. But when ran, the program
generated a SIGSEGV error. I debugged it using gdb and found that ,when
the symbol returned by dlsym() was invoked, the resulting value was
null.
I couldn't understand clearly why it didn't worked. The problematic
location in the code
has been denoted below(calc.cpp):
calc.cpp:
#include "calculator.hpp"
typedef Math* (*factory)(void);
bool Calculator::load(char* library_name) {
factory make;
/* Open shared library */
handle = dlopen(library_name, RTLD_NOW);
if (!handle) {
cout << dlerror();
return false;
}
/* Load symbols from library */
make = (factory)dlsym(handle, "maker");
if (make = NULL) {
cout << dlerror() << "\n";
return false;
}
/* Construct object */
math = (*make)(); ===> *** This is Problem location***
cout << (void*)math << "\n";
return true;
}
bool Calculator::calculate() {
float a;
cout << "Enter float:\n";
fscanf(stdin,"%f",&a);
c = math->square(a);
cout << "Square: " << c << '\n";
return true;
}
bool Calculator::close() {
char *error;
dlerror();
dlclose(handle);
if ((error = dlerror()) != NULL) {
cout << error;
return false;
}
return true;
}
main.cpp:
#include "calculator.hpp"
int main (int argc, char* argv[]) {
if (argc != 2)
cout << "Usage: calc \n";
Calculator* c = new Calculator();
if (c->load(argv[1])) {
c->calculate();
c->close();
}
delete c;
return 0;
}
calculator.hpp:
#ifndef __CALCULATOR_H
#define __CALCULATOR_H
#include "math.hpp"
class Calculator {
public:
bool load(char* library);
bool calculate();
bool close();
private:
void* handle;
Math* math;
};
#endif
math.hpp:
#ifndef __MATH_H
#define __MATH_H
class Math {
public:
virtual float multiply(float a, float b);
virtual float square(float a);
};
#endif
math.cpp:
#include "math.hpp"
float Math::multiply(float a, float b) {
return a*b;
}
float Math::square(float a) {
return a*a;
}
extern "C" {
Math *maker() {
return new Math;
}
}
I'm using g++ 3.2.3 and below is the makefile used to compile the
program.
LIB_SRC = math.cpp
LIB_OBJ = math.o
LIB = math
BIN_SRC = main.cpp calc.cpp
BIN = calc
LIB_VER_MAJOR =
LIB_VER_MINOR =
CC = g++
LIB_OBJ_FLAGS = -fPIC -c -Wall -g
LIB_SO_FLAGS = -shared -lc -Wl,-soname
BIN_FLAGS = -rdynamic -ldl -Wall -g
all: lib.o lib.so bin
lib.o:
$(CC) $(LIB_OBJ_FLAGS) $(LIB_SRC)
lib.so:
$(CC) $(LIB_SO_FLAGS),$(LIB).so.$(LIB_VER_MAJOR) \
-o $(LIB).so$(LIB_VER_MAJOR)$(LIB_VER_MINOR) $(LIB_OBJ)
bin:
$(CC) $(BIN_FLAGS) -o $(BIN) $(BIN_SRC)
clean:
rm -f *.o *.so* $(BIN)
Any pointers/suggestions to solve this problem will be really
appreciated. The argument to calc exe is math.so
Thanks & Regards,
Karthik D