CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 10 of 10
  1. #1
    Join Date
    Jul 2007
    Posts
    7

    Exclamation Problem while calling a method in an .so file

    Hi,

    I have the following code which attempts to load and call a function from a .so file:

    Code:
    1) CTEST.h : the same header which is included in the .so
    
    #ifndef CTEST_H_
    #define CTEST_H_
    #include <iostream>
    #include <stdio.h>
    using namespace std;
    
    class CTEST {
    	
    	public:
    	
    		CTEST ();
    		virtual ~CTEST();
    	
    		int* ctest1(int i);
    		int* ctest2(int i);
    		
    	private:
    
    		int i;
    };
    
    typedef CTEST* create_t();
    typedef void destroy_t(CTEST*);
    
    #ifdef __cplusplus
    extern "C" {
    #endif	
    
    extern "C" CTEST* create(); 
    extern "C" void destroy(CTEST* p);
    
    #ifdef __cplusplus
    }
    #endif
    
    #endif /*CTEST_H_*/
    2) soprog.cpp: program that loads loadctest.so file and tries to call the method ctest2():

    Code:
    #include <dlfcn.h>
    #include "CTEST.h"
    
    
    int main(int argc, char **argv) 
    {
       void *lib_handle;
       int x = 5;
       char *error;
    
       lib_handle = dlopen("/usr/local/lib/libctest.so", RTLD_LAZY);
       if (!lib_handle) 
       {
          cout<<dlerror()<<endl;
          exit(1);
       }
    
       create_t* create_ctest = (create_t*) dlsym(lib_handle, "create");
       if ((error = dlerror()) != NULL)  
       {
          cout<<dlerror()<<endl;
          exit(1);
       }
    
       destroy_t* destroy_ctest = (destroy_t*) dlsym(lib_handle, "destroy");
       
       CTEST* tobj = create_ctest();
       
       int* retval = tobj->ctest2(x);
       
       //cout<<*retval<<endl;
    	
       destroy_ctest(tobj);
       dlclose(lib_handle);
       return 0;
    }

    The problem I have been facing is the following call gets called:

    CTEST* tobj = create_ctest();

    As it shows the messages it has in its constructor, thus validating the correct .so loaded and method called.

    But whenever I am trying to call the ctest2() method in the following line:

    int* retval = tobj->ctest2(x);

    The ld is giving the following error message:

    soprog.cpp.text+0x200): undefined reference to `CTEST::ctest2(int)'
    collect2: ld returned 1 exit status

    Can somebody help me in this?

    Thanks a lot.
    -PD

  2. #2
    Join Date
    Mar 2004
    Location
    (Upper-) Austria
    Posts
    2,899

    Re: Problem while calling a method in an .so file

    Have you tried making your member methods virtual?

    Btw: I learned it upon this tutorial: http://www.linuxjournal.com/article/3687
    I am not offering technical guidiance via email or IM
    Come on share your photo with us! CG members photo album!
    Use the Code Tags!

  3. #3
    Join Date
    Oct 2000
    Location
    London, England
    Posts
    4,773

    Re: Problem while calling a method in an .so file

    Are you sure you remembered to add a definition for that method in your library?

  4. #4
    Join Date
    Jul 2007
    Posts
    7

    Exclamation Re: Problem while calling a method in an .so file

    Here follows the simple code which the libctest.so file consists of:

    Code:
    #include "CTEST.h"
    using namespace std;
    
    CTEST::CTEST(){
    	std::cout<<"CTEST Initialized..."<<std::endl;
    }
    
    CTEST::~CTEST(){
    	std::cout<<"CTEST Deinitialized..."<<std::endl;
    }
    
    CTEST* create() {
        return new CTEST;
    }
    
    void destroy(CTEST* p) {
        delete p;
    }
    
    int* CTEST::ctest1(int x)
    {
       this->i = x;
       std::cout<<"In CTEST::ctest2(). i is "<<this->i<<std::endl;
       
       return &this->i;
    }
    
    int* CTEST::ctest2(int x)
    {
       this->i = x * x;
       std::cout<<"In CTEST::ctest2(). i is "<<this->i<<std::endl;
       
       return &this->i;
    }

    As you can see the ctest2 method is defined. Also as a proof of my earlier post that the file is loaded please check the output below when I call

    CTEST* tobj = create_ctest();

    Output:

    CTEST Initialized...
    CTEST Deinitialized...

    The problem occurs only when I try to call the following:

    int* retval = tobj->ctest2(x);

    Is there anything to do with the Cygwin and g++ I am using?

    -Thanks,
    PD

  5. #5
    Join Date
    Aug 2005
    Location
    LI, NY
    Posts
    576

    Re: Problem while calling a method in an .so file

    As far as the linker knows, there is no implementation for those methods; the implementation in the .so is not known until runtime. Constructors and destructors work because those calls occur within the shared object.

    When you created libctest.so, did it create libctest.a as well? If so, linking against that should fix this problem. Otherwise, make CTEST purely interface, and implement it with a subclass in the .so library (and that is only used directly by the .so library).

  6. #6
    Join Date
    Jul 2007
    Posts
    7

    Re: Problem while calling a method in an .so file

    Quote Originally Posted by Hermit
    As far as the linker knows, there is no implementation for those methods; the implementation in the .so is not known until runtime. Constructors and destructors work because those calls occur within the shared object.

    When you created libctest.so, did it create libctest.a as well? If so, linking against that should fix this problem. Otherwise, make CTEST purely interface, and implement it with a subclass in the .so library (and that is only used directly by the .so library).

    But that's why we used -ldl, isn't it?

    Wy I need to create an .a file. I should not bother abt that file since I hav exreated an .so, right?

    Not sure what you meant by "CTEST purely interface". Are you saying to make everything pure virtual?

    Pease help.

    -PD.

  7. #7

    Re: Problem while calling a method in an .so file

    What you are doing is creating an interface class and getting a pointer to it via an exported function.

    To correctly make this work, you will need to make your destructor and methods that you want to use virtual, otherwise, in a dynamically loaded .SO (works the same for *.DLLs on Windows) you do not know the address of the function. Since the function is not virtual, that means it is not in a VTABLE. However, if it is virtual, a VTABLE will exist in the object, and therefore the address of the function can be found.

    Having a PURE VIRTUAL base class, and then hidden sub classes that implement that interface could allow you to have more than 1 definition of the interface you define. That is the basis of 'plugin development'.

  8. #8
    Join Date
    Jul 2007
    Posts
    7

    Re: Problem while calling a method in an .so file

    Quote Originally Posted by JamesSchumacher
    What you are doing is creating an interface class and getting a pointer to it via an exported function.

    To correctly make this work, you will need to make your destructor and methods that you want to use virtual, otherwise, in a dynamically loaded .SO (works the same for *.DLLs on Windows) you do not know the address of the function. Since the function is not virtual, that means it is not in a VTABLE. However, if it is virtual, a VTABLE will exist in the object, and therefore the address of the function can be found.

    Having a PURE VIRTUAL base class, and then hidden sub classes that implement that interface could allow you to have more than 1 definition of the interface you define. That is the basis of 'plugin development'.

    First:

    Tried your virtual thing and this is the outcome:


    g++ -Wall -L.:/usr/local/lib soprog.cpp -ldl -o soprog
    soprog.cpp: In function `int main(int, char**)':
    soprog.cpp:29: warning: unused variable 'retval'
    /cygdrive/c/DOCUME~1/PRANAB~1/LOCALS~1/Temp/ccTnPw8A.o:soprog.cpp.text+0x200): undefined reference to `CTEST::ctest2(int)'
    collect2: ld returned 1 exit status
    make: *** [soprog] Error 1
    make: Target `all' not remade because of errors.


    Thanks,
    PD

  9. #9
    Join Date
    Oct 2000
    Location
    London, England
    Posts
    4,773

    Re: Problem while calling a method in an .so file

    Code:
    class CTEST 
    {
      public:
       CTEST ();
      virtual ~CTEST();
    	
       virtual int* ctest1(int i);
       virtual int* ctest2(int i);
    		
    private:
    
        int i;
    };
    Also check your compiler options, are they both being compiler with the same compiler, etc. You may need -fPIC for your library.

  10. #10
    Join Date
    Jul 2007
    Posts
    7

    Smile Re: Problem while calling a method in an .so file

    Hi Everbody,

    Thanks for the explanations and it indeed worked when the method entrires are in vtable.

    Thanks again.

    -PD.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured