LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 08-14-2008, 05:41 PM   #1
hwoarang
Member
 
Registered: Aug 2008
Posts: 31

Rep: Reputation: 15
Using shared libs


Hi all,

I have made a programme that uses a shared lib as a class factory. The problem is that the classes from the factory use a class named Element. So as the main program. When I compile and link, I have to include the element class in both main and library. Otherwise, it doesn't link.

Is there a way to include the ELment class only once ?

Thanks
 
Old 08-14-2008, 05:48 PM   #2
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Are you talking about the class definition, or the definitions of its functions? Are you talking about inadvertently #include-ing the same file twice?
ta0kira
 
Old 08-15-2008, 10:25 AM   #3
hwoarang
Member
 
Registered: Aug 2008
Posts: 31

Original Poster
Rep: Reputation: 15
Thanks for the answer. I am talking about the cpp file. Iunderstand that the header file is mandatory, especially if the classes are used. But I would think that the cpp file defining the functions should be included only once (in the main program or in the library) and used during the link.
 
Old 08-15-2008, 02:24 PM   #4
paulsm4
LQ Guru
 
Registered: Mar 2004
Distribution: SusE 8.2
Posts: 5,863
Blog Entries: 1

Rep: Reputation: Disabled
Assuming your "class factory" is in a Linux shared library (.so), and further assuming your code doesn't explicitly instantiate any instances of any of the derived types your "factory" produces, I think you've basically got two alternatives:

a) Declare dummy static variables (just to force the linker to bring in the code)
... or ...
b) Manually invoke dlopen(), dlsym() and friends:

http://linux.about.com/library/cmd/blcmdl3_dlsym.htm
 
Old 08-16-2008, 04:44 AM   #5
hwoarang
Member
 
Registered: Aug 2008
Posts: 31

Original Poster
Rep: Reputation: 15
Quote:
Originally Posted by paulsm4 View Post
Assuming your "class factory" is in a Linux shared library (.so)
That's the case.

Quote:
Originally Posted by paulsm4 View Post
assuming your code doesn't explicitly instantiate any instances of any of the derived types your "factory" produces
Yes but the problem is not with the derived types the factory produces, it is with some classes used by the derived classes AND the main program.

Quote:
Originally Posted by paulsm4 View Post
b) Manually invoke dlopen(), dlsym()
THat's what I use ;-)

I'm not sure I was clear enough so here is some code showing where the problem lies :
Main program :
Code:
#include "Element.hpp"

Element e1;
Derived *p;
Derived *(*pInvoke)();

/* I use the Element class in main program */
e1.diplay();

/* I use dlopen/dlsym to get a pointer to the factory */
p = pInvkoke();

/* The derived class also uses and instanciates the derived class */
p.display_element();
Derived class :
Code:
class c1 : public Derived
{
/* Some functional private code */
void display_element()
{
   Element e;
   e.display_element();
}
}
In that example, the problem is that I have to include the Element.cpp defining the Element class in both main and shared library. From my point of view, it should be enough to have the Element.cpp file in the main program, not in the shared lib. The shared lib should use only the Element.hpp and it should be linked to the functions declared in Element.cpp when linking (when it is loaded).

Is it possible to do this ?

Thanks
 
Old 08-16-2008, 07:29 PM   #6
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Quote:
Originally Posted by paulsm4 View Post
a) Declare dummy static variables (just to force the linker to bring in the code)
This should only be necessary to instantiate templates, though you might have a problem with in-context function definitions being optimized out as unused inlines. I think the problem here might be a .cpp with both the class declaration and the function definitions in it.
ta0kira

Last edited by ta0kira; 08-16-2008 at 07:35 PM.
 
Old 08-20-2008, 02:18 AM   #7
hwoarang
Member
 
Registered: Aug 2008
Posts: 31

Original Poster
Rep: Reputation: 15
For information, I was able to solve this problem by using the flag -rdynamic when linking the main executable. It allows to export the symbols from the main executable to the dynamically loaded library. Then, there is no more link problem when the shared library is loaded, even if it has been built without the Element.cpp file.

Thanks for the help anyway

Last edited by hwoarang; 08-20-2008 at 02:20 AM.
 
Old 08-20-2008, 02:09 PM   #8
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
I think I understand your problem now. Normally it's better to solve the problem without additional build options, so normally one would link the base class into a shared library then link both the main program and the library with the derived class to the base class' library:
Code:
//base.hpp


struct base_class
{
    base_class();

    virtual void function() = 0;

    virtual ~base_class();
};

extern "C" {
extern base_class *factory_function();
}
Code:
//base.cpp

#include <iostream>
#include "base.hpp"


base_class::base_class() { std::cout << "create base_class\n"; }

base_class::~base_class() { std::cout << "destroy base_class\n"; }
Code:
//derived.cpp

#include <iostream>
#include "base.hpp"


class my_class : public base_class
{
    void function()
    { std::cout << "my_class virtual function\n"; }
};

base_class *factory_function()
{ return new my_class; }
Code:
//main.cpp

#include <iostream>
#include <dlfcn.h>
#include "base.hpp"


int main(int argc, char *argv[])
{
    for (int I = 1; I < argc; I++)
    {
    void *library = dlopen(argv[I], RTLD_NOW);

    if (!library)
     {
    std::cerr << argv[0] << ": library open error: " << dlerror() << "\n";
    continue;
     }

    base_class*(*create)() = (base_class*(*)()) dlsym(library, "factory_function");

    if (!create)
     {
    std::cerr << argv[0] << ": function load error: " << dlerror() << "\n";
    continue;
     }

    base_class *new_object = (*create)();

    if (new_object)
     {
    new_object->function();
    delete new_object;
     }
    }
}
Code:
g++ -shared base.cpp -o base.so
g++ main.cpp -o main ./base.so -ldl
g++ -shared derived.cpp -o derived.so ./base.so
Code:
./main ./derived.so
create base_class
my_class virtual function
destroy base_class
ta0kira
 
  


Reply



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 Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
shared libs help spatula Linux - Software 3 12-14-2005 03:48 AM
Recompile ALL shared libs? ta0kira Programming 3 06-13-2005 12:49 AM
chroot and shared libs not being found. netstv Linux - General 3 11-05-2004 11:36 AM
Qt Libs Static or Shared magicm Slackware 2 10-15-2003 05:05 AM
shared libs hanzerik Linux From Scratch 2 03-14-2002 01:08 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 03:04 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration