dlsym and function pointer ...

Discussion in 'C++' started by dkarthik@gmail.com, Dec 13, 2005.

  1. Guest

    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
     
    , Dec 13, 2005
    #1
    1. Advertising

  2. mlimber Guest

    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-lite/how-to-post.html#faq-5.9

    Cheers! --M
     
    mlimber, Dec 13, 2005
    #2
    1. Advertising

  3. Artie Gold Guest

    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!"
     
    Artie Gold, Dec 13, 2005
    #3
  4. 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/html/group__GenericFactories.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::DKy );
    ----------------------------------------------------

    ------------------ 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.
     
    Gianni Mariani, Dec 13, 2005
    #4
  5. Guest

    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
     
    , Dec 14, 2005
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. glen stark
    Replies:
    2
    Views:
    708
    Ron Natalie
    Oct 10, 2003
  2. Mike D.

    Passing pointer to function using DLSYM()

    Mike D., Jan 12, 2004, in forum: C Programming
    Replies:
    7
    Views:
    399
    Christopher Benson-Manica
    Jan 13, 2004
  3. Replies:
    0
    Views:
    527
  4. anonimo
    Replies:
    3
    Views:
    1,241
    BGB / cr88192
    Jan 2, 2010
  5. Replies:
    8
    Views:
    518
Loading...

Share This Page