dlsym and function pointer ...

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • dkarthik@gmail.com

    #1

    dlsym and function pointer ...

    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::loa d(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::cal culate() {

    float a;
    cout << "Enter float:\n";
    fscanf(stdin,"% f",&a);

    c = math->square(a);

    cout << "Square: " << c << '\n";
    return true;
    }

    bool Calculator::clo se() {
    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(fl oat 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.$(LI B_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

  • mlimber

    #2
    Re: dlsym and function pointer ...

    dkart...@gmail. com wrote:[color=blue]
    > 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::loa d(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::cal culate() {
    >
    > float a;
    > cout << "Enter float:\n";
    > fscanf(stdin,"% f",&a);
    >
    > c = math->square(a);
    >
    > cout << "Square: " << c << '\n";
    > return true;
    > }
    >
    > bool Calculator::clo se() {
    > 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(fl oat 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.$(LI B_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[/color]

    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:



    Cheers! --M

    Comment

    • Artie Gold

      #3
      Re: dlsym and function pointer ...

      dkarthik@gmail. com wrote:[color=blue]
      > 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.[/color]

      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. ;-)[color=blue]
      >
      > 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::loa d(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) {[/color]

      No matter *what* dlsym() returned, you just set it to NULL in the above
      line!!!! [Hint: *Turn up the warning level on your compile*!!]
      [color=blue]
      > cout << dlerror() << "\n";
      > return false;
      > }
      >
      > /* Construct object */
      > math = (*make)(); ===> *** This is Problem location***[/color]

      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!"

      Comment

      • Gianni Mariani

        #4
        Re: dlsym and function pointer ...

        dkarthik@gmail. com wrote:
        ....[color=blue]
        > Any pointers/suggestions to solve this problem will be really
        > appreciated. The argument to calc exe is math.so[/color]

        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.


        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_MakeFactory0 P( "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::FactoryRegi ster< 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
        FactoryRegister Registry::Get() function gets installed, otherwise it
        won't work with multiple factory registries.

        Comment

        • dkarthik@gmail.com

          #5
          Re: dlsym and function pointer ...

          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

          Comment

          Working...