You are not logged in.

#1 2009-08-04 14:49:28

ngoonee
Forum Fellow
From: Between Thailand and Singapore
Registered: 2009-03-17
Posts: 7,356

C++ dynamically load libraries (dlopen) with virtual functions?

Hi all, I've hit upon dynamically loading libraries using dlopen and extern "C" based on previous advise from these forums. Followed the instructions here with no big issue, but was unable to convert my (obviously much more complicated) classes.

Basically, things compile fine, but I get 'undefined symbol' errors which seem to refer to a base class along the heirarchy rather than the library itself, but which prevents me at runtime from loading the library.

So, for a simple example (note, this isn't real code as its nearing midnight here, and I have no clue how to simplify my real code to the smallest fragment which shows the issue, will try again tomorrow)...

I have class A, class B which inherits publicly from A, and class C which inherits publicly from B. Class A defines several virtual functions, which are redefined virtual in B and only given concrete implementations in C.

Compiling goes fine, but at runtime I get the 'undefined symbol' error which is specifically referring to one of the virtual functions, but from class B (shows an error with what I think looks like the mangled name of B compiled with the function name combined with the types of the arguments).

I tried making C inherit from A (by duplicating the code which was generalized through B) but this just 'moved' the error into A instead of B, same syntax. Total removal of the offending function instead gives the 'undefined error' saying that the symbol for class A doesn't exist.

I'm aware this isn't a very good explanation since I don't have the minimal example. Will try to get it as soon as possible tomorrow. In the meantime, any ideas to focus my trouble-shooting are much appreciated.


Allan-Volunteer on the (topic being discussed) mailn lists. You never get the people who matters attention on the forums.
jasonwryan-Installing Arch is a measure of your literacy. Maintaining Arch is a measure of your diligence. Contributing to Arch is a measure of your competence.
Griemak-Bleeding edge, not bleeding flat. Edge denotes falls will occur from time to time. Bring your own parachute.

Offline

#2 2009-08-04 15:56:34

scio
Member
From: Buffalo, NY
Registered: 2008-08-05
Posts: 366

Re: C++ dynamically load libraries (dlopen) with virtual functions?

Just to throw a little more information out there:

Are A, B, and C all inside the library?

ngoonee wrote:

Class A defines several virtual functions, which are redefined virtual in B and only given concrete implementations in C.

Does this mean in C you declare them not virtual? Or, if B is still pure virtual you do not need to have them there.

I'll simmer on this for a while to see if I can remember anything else that might be missing.

Offline

#3 2009-08-04 22:20:57

ngoonee
Forum Fellow
From: Between Thailand and Singapore
Registered: 2009-03-17
Posts: 7,356

Re: C++ dynamically load libraries (dlopen) with virtual functions?

I'm not sure what you mean by 'inside the library'. In the sense that I include their headers at compile-time of the library, then of course (can't inherit from B without including B's header I think).

The functions are virtual (not pure virtual) with default implementation in A and B. They are no longer virtual in C. I have a few functions of this type, but I just realized the one giving me problems is an overloaded function.

So say we have (somewhat pseudo-code, leaving for work soon):-

class A {
public:
  virtual void run(int* const) { *default implementation* }
  virtual void run(short* const, unsigned char* const) { *default implementation* }
*rest of class goes here*
};

class B : public A {
public:
  virtual void run(int* const) { *alternative default implementation* }
  virtual void run(short* const, unsigned char* const) { *alternative default implementation* }
*rest of class goes here*
};

class C : public B {
public:
  void run(int* const) { *my implementation* }
  void run (short* const, unsigned char* const) { *my implementation* }
*rest of class goes here*
};

Its probably worth noting that this works perfectly fine when C is compiled into the executable (directly #include-d and used), my problem is when using dlopen and extern "C" plus 2 global functions which create and destroy an instance of C, but are used in main { } as A objects (polymorphism).


Allan-Volunteer on the (topic being discussed) mailn lists. You never get the people who matters attention on the forums.
jasonwryan-Installing Arch is a measure of your literacy. Maintaining Arch is a measure of your diligence. Contributing to Arch is a measure of your competence.
Griemak-Bleeding edge, not bleeding flat. Edge denotes falls will occur from time to time. Bring your own parachute.

Offline

#4 2009-08-05 00:44:08

scio
Member
From: Buffalo, NY
Registered: 2008-08-05
Posts: 366

Re: C++ dynamically load libraries (dlopen) with virtual functions?

ngoonee wrote:

I'm not sure what you mean by 'inside the library'. In the sense that I include their headers at compile-time of the library, then of course (can't inherit from B without including B's header I think).

Did you compile the library? If so, are all 3 classes compiled into the library? (Did you include the .cpp files when you built it).

If you didn't compile the library, which of the classes are from the library and which are you creating?

From the explanation, it sounds like only C is in the library which doesn't make sense since the library would need the definitions of A and B.

Offline

#5 2009-08-05 00:50:52

ngoonee
Forum Fellow
From: Between Thailand and Singapore
Registered: 2009-03-17
Posts: 7,356

Re: C++ dynamically load libraries (dlopen) with virtual functions?

I'm actually using Eclipse CDT, but I believe what is being done (I have the appropriate includes) is that the .h files are included, and those are sufficient for compiling the lib. Whether it refers to the .cpp I have no idea, but I know that changes in the cpp would prompt a rebuild on the library (even though the cpp isn't within the project as defined by Eclipse).

The library itself, in the Eclipse project, is just a single cpp containing includes of B.h and A.h and the definition of class C. I'll check out whether putting the complete definitions for A and B within their headers works.


Allan-Volunteer on the (topic being discussed) mailn lists. You never get the people who matters attention on the forums.
jasonwryan-Installing Arch is a measure of your literacy. Maintaining Arch is a measure of your diligence. Contributing to Arch is a measure of your competence.
Griemak-Bleeding edge, not bleeding flat. Edge denotes falls will occur from time to time. Bring your own parachute.

Offline

#6 2009-08-05 02:29:00

ngoonee
Forum Fellow
From: Between Thailand and Singapore
Registered: 2009-03-17
Posts: 7,356

Re: C++ dynamically load libraries (dlopen) with virtual functions?

Now that's interesting. Including A.cpp instead of A.h makes it work. More investigation revealed that I had to make sure the implementations of the virtual functions are included in the header which I include in class C.

It may be that using A.o and B.o in linking my C.so would also solve this. Unfortunately Eclipse CDT seems a bit picky on only including .cpp (and therefore .so) which are within a project...

Please inform me if my analysis (admittedly based only only an hour of testing) above is correct, as I do want and need to understand this.

EDIT: Just to add that in B I use a virtual function (bar1) and a protected template function (bar2) which it calls, so I cannot only place the implementation for the virtual function bar1, I must have the full implementation for bar2 available when bar1 is compiled. This makes my header file unreadable though...

Anyway, I've tried with adding the .o files to the g++ -shared ..., and that works. I guess I'll have to bug the Eclise CDT team about this.

Last edited by ngoonee (2009-08-05 02:59:12)


Allan-Volunteer on the (topic being discussed) mailn lists. You never get the people who matters attention on the forums.
jasonwryan-Installing Arch is a measure of your literacy. Maintaining Arch is a measure of your diligence. Contributing to Arch is a measure of your competence.
Griemak-Bleeding edge, not bleeding flat. Edge denotes falls will occur from time to time. Bring your own parachute.

Offline

#7 2009-08-05 11:26:28

Cerebral
Forum Fellow
From: Waterloo, ON, CA
Registered: 2005-04-08
Posts: 3,108
Website

Re: C++ dynamically load libraries (dlopen) with virtual functions?

So that's your problem - you're trying to link together a library that has undefined methods, just like the error says.

The methods are declared in the header files (A.h and B.h) but they're _defined_ in the .cpp files (and resulting .o files that come out of compilation) - you need to link together A.o, B.o, C.o in the library for the linker to not complain.

Also, technically, even though you didn't use the keyword "virtual" in class C, the methods are still virtual since they override virtual base-class methods - they _have_ to be virtual for things to work right.  I'd suggest sticking the 'virtual' keyword on there just so it's clearer to the reader, but I don't think it makes a difference - they are virtual methods.

-edit- also, you're right that the template method has to be defined in the header for things to work out nicely, but that doesn't have to make your header unreadable.  You can do something like this to separate the implementation from the interface:

#ifndef _B_HEADER_
#define _B_HEADER_

// Define the class first
class B
{
protected:
    template<class MyClass>
    void myMethod(MyClass m);
public:
    // rest of class interface here.
};

// Now actually define the template method, separate from the class.  Improved readability FTW!
template<class MyClass>
void B::myMethod(MyClass m)
{
    // implementation of template method here.
}

#endif

Last edited by Cerebral (2009-08-05 11:31:15)

Offline

#8 2009-08-05 12:31:56

scio
Member
From: Buffalo, NY
Registered: 2008-08-05
Posts: 366

Re: C++ dynamically load libraries (dlopen) with virtual functions?

Cerebral wrote:

Also, technically, even though you didn't use the keyword "virtual" in class C, the methods are still virtual since they override virtual base-class methods - they _have_ to be virtual for things to work right.  I'd suggest sticking the 'virtual' keyword on there just so it's clearer to the reader, but I don't think it makes a difference - they are virtual methods.

The first part is correct, but the reason for leaving out virtual is so that if a class inherts from C it cannot override the run methods when referenced as the base class.  So yes, in the case of C they are virtual functions but if there was a

class D : public C{
public:
  void run(int* const) { *my implementation* }
  void run (short* const, unsigned char* const) { *my implementation* }
*rest of class goes here*
};

int main(int argc, char* argv[]) {
   C myD = new D();
   D realD = new D();
   myD.run(0);
   realD.run(0);
   delete myD;
   delete realD;
return 0;
}

myD.run(0) would call C's run while realD would call D's.

Hopefully between Cerebral's post and my prodding you have figured a few things out.  Not to be offensive, but have you done much programming with C++ and inheritance?
You might want to look at:
http://www.e-booksdirectory.com/programming.php#cpp
A good starting point is:
http://www.pragsoft.com/books/CppEssentials.pdf
It is slightly C biased (avoids STL etc.) but it will give you some of the basics with things like inheritance.

Edit: Corrected wording after reading it.

Last edited by scio (2009-08-05 16:32:28)

Offline

#9 2009-08-05 13:04:21

Cerebral
Forum Fellow
From: Waterloo, ON, CA
Registered: 2005-04-08
Posts: 3,108
Website

Re: C++ dynamically load libraries (dlopen) with virtual functions?

scio wrote:

The first part is correct, but the reason for leaving out virtual is so that if a class inherts from C it cannot override the run methods.

Well I'll be damned - didn't know that.  Sounds like it could make things confusing though.

Offline

#10 2009-08-05 16:25:54

gnud
Member
Registered: 2005-11-27
Posts: 182

Re: C++ dynamically load libraries (dlopen) with virtual functions?

I suggest that both ngoonee and Cerebral read the tutorial at http://www.linuxjournal.com/article/3687

Offline

#11 2009-08-05 20:24:44

Cerebral
Forum Fellow
From: Waterloo, ON, CA
Registered: 2005-04-08
Posts: 3,108
Website

Re: C++ dynamically load libraries (dlopen) with virtual functions?

gnud wrote:

I suggest that both ngoonee and Cerebral read the tutorial at http://www.linuxjournal.com/article/3687

Nice tutorial.  Covers some good material for making extensible plugins - pure virtual classes and a creative use of a map as a factory.  I'll have to remember that URL if I'm ever designing something like this.

Offline

#12 2009-08-05 23:05:15

ngoonee
Forum Fellow
From: Between Thailand and Singapore
Registered: 2009-03-17
Posts: 7,356

Re: C++ dynamically load libraries (dlopen) with virtual functions?

Cerebral wrote:

Also, technically, even though you didn't use the keyword "virtual" in class C, the methods are still virtual since they override virtual base-class methods - they _have_ to be virtual for things to work right.  I'd suggest sticking the 'virtual' keyword on there just so it's clearer to the reader, but I don't think it makes a difference - they are virtual methods.

As scio said, I make the final one non-virtual to make it clear its not to be inherited from. I also have a private (not protected) constructor for the same reason, on the final one.

scio wrote:

Hopefully between Cerebral's post and my prodding you have figured a few things out.  Not to be offensive, but have you done much programming with C++ and inheritance?
You might want to look at:
http://www.e-booksdirectory.com/programming.php#cpp
A good starting point is:
http://www.pragsoft.com/books/CppEssentials.pdf
It is slightly C biased (avoids STL etc.) but it will give you some of the basics with things like inheritance.

Edit: Corrected wording after reading it.

No offense taken, I have been using C++ for various things for quite a few years, but only recently (less than a month ago) actually tried to use inheritance. I was actually using C, I guess, but with classes and a C++ compiler. I've actually been through stuff like the C++ FAQ Lite and the link gnud put up, but the thing I don't really like about those documents is that some things are assumed (for example, the linking of .o files isn't explicitly mentioned in either), so my prior assumptions, such as that a library which compiles AND links properly should be fine, weren't corrected.

Concerning C++ related textbooks, I'm reading some which are on the FAQ Lite's list, one for legality and one for morality as recommended. It does take a bit too much time when I'm supposed to be working on my thesis though, so those are slowly being gone through. Will take a look on the legality guide for inheritence, I'd already been through the morality one (which basically said things like 'AVOID DIAMONDS IF POSSIBLE' and 'KNOW WHAT YOU MEAN WITH PUBLIC/PRIVATE INHERITANCE').


Allan-Volunteer on the (topic being discussed) mailn lists. You never get the people who matters attention on the forums.
jasonwryan-Installing Arch is a measure of your literacy. Maintaining Arch is a measure of your diligence. Contributing to Arch is a measure of your competence.
Griemak-Bleeding edge, not bleeding flat. Edge denotes falls will occur from time to time. Bring your own parachute.

Offline

Board footer

Powered by FluxBB