Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > dlsym and function pointer ...

Reply
Thread Tools

dlsym and function pointer ...

 
 
dkarthik@gmail.com
Guest
Posts: n/a
 
      12-13-2005
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

 
Reply With Quote
 
 
 
 
mlimber
Guest
Posts: n/a
 
      12-13-2005
(E-Mail Removed) wrote:
> 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


Greetings and welcome to comp.lang.c++. Unfortunately, because dlsym()
is not a standard library function, this question is outside the scope
of this newsgroup, which is intended for discussions of the language
itself rather than third-party library or platform-specific questions.
I'd suggest you post in a newsgroup for your platform or compiler. See
the FAQ for some suggestions of where to post:

http://www.parashift.com/c++-faq-lit...t.html#faq-5.9

Cheers! --M

 
Reply With Quote
 
 
 
 
Artie Gold
Guest
Posts: n/a
 
      12-13-2005
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
> 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.


Though dlsym() is not part of standard C++ (and therefore off topic) you
have a rather different problem in your code -- of the `Doh!' variety.

See below. You've been thinking too hard.
>
> 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) {


No matter *what* dlsym() returned, you just set it to NULL in the above
line!!!! [Hint: *Turn up the warning level on your compile*!!]

> cout << dlerror() << "\n";
> return false;
> }
>
> /* Construct object */
> math = (*make)(); ===> *** This is Problem location***


Well, no it's not. See above.

[snip]

HTH,
--ag
--
Artie Gold -- Austin, Texas
http://goldsays.blogspot.com (new post 8/5)
http://www.cafepress.com/goldsays
"If you have nothing to hide, you're not trying!"
 
Reply With Quote
 
Gianni Mariani
Guest
Posts: n/a
 
      12-13-2005
(E-Mail Removed) wrote:
....
> Any pointers/suggestions to solve this problem will be really
> appreciated. The argument to calc exe is math.so


Don't use dlsym. Look at somthing like Austria C++ generic factories.
It is a standard C++ way of doing the same thing. No need to use extern
"C".

The documentation has alot to be desired.
http://austria.sourceforge.net/dox/h...Factories.html

Basically, you define an interface class.

class MakerIF
{
public:
virtual void f() = 0;
};

Then in the file that makes the shared object (.so or .dll file).

----------------- impl.cpp -------------------------
#include "at_factory.h"
#include "app_interface.h"
class MakerImpl
: public MakerIF
{
public:
virtual void f()
{
Stuff();
}
};

// Register the factory
AT_MakeFactory0P( "NameOfImpl", MakerIF, MakerImpl, at:Ky );
----------------------------------------------------

------------------ main app code -------------------
#include "at_factory.h"
#include "app_interface.h"

int main()
{

void * dlhnd = dlopen( "impl.so" );

MakerIF * obj = at::FactoryRegister< MakerIF >
::Get().Create( "NameOfImpl" )();

if ( obj )
{
obj->f();
}
}
-----------------------------------------------------

Admitedly, it's been a while since I tested using dlopen(), but it
should be no issue. You will need to use Austria C++ as a .so/dll to
make this work or there needs to be exactly one place where the
FactoryRegisterRegistry::Get() function gets installed, otherwise it
won't work with multiple factory registries.
 
Reply With Quote
 
dkarthik@gmail.com
Guest
Posts: n/a
 
      12-14-2005
Hi Ag,

Thanks for pointing it out. It didn't striked me. Once I modified that,
it worked fine. Once again thanks.


Thanks & Regards,

Karthik D

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Possible workaround for dlsym() and cast from/to void* anonimo C++ 3 01-02-2010 02:09 PM
Calling dlsym()-ed function causes segfault nirnimesh@gmail.com C++ 0 08-12-2006 08:40 PM
Unresolved symbols dlclose, dlopen, dlerror, dlsym me2faster@excite.com Ruby 8 05-17-2005 07:30 PM
Passing pointer to function using DLSYM() Mike D. C Programming 7 01-13-2004 06:35 PM
function pointer and member function pointer question glen stark C++ 2 10-10-2003 01:41 PM



Advertisments