C ++ dlopen mini howto a good introduction to C ++ dlopen Linux/Mac OS X programming materials

Source: Internet
Author: User
C ++ dlopen mini howto
By Aaron isotton <aaron@isotton.com>
Lolita@linuxsir.org

------------------------------------------------
Summary
How to Use the dlopen API to dynamically load C ++ functions and Classes
------------------------------------------------
Directory
Introduction
Copyright and license
No commitment
Contributor
Feedback
Terms
Problem
Name mangling
Class
Solution
Extern "C"
Load Functions
Load class
Source code
FAQ
Others
Reference books
------------------------------------------------
Introduction
How to Use the dlopen API to dynamically load C ++ functions and classes is unix c ++ProgramFrequently encountered problems. In fact, the situation is occasionally complicated and requires some explanation. This is why I wrote this mini howto article.
The premise of understanding this document is to have a basic understanding of dlopen APIs in C/C ++. The maintenance link of this howto is http://www.isotton.com/howtos/C++-dlopen-mini-HOWTO/

Copyright and license
This article "C ++ dlopen mini howto" is copyrighted by Aaron isotton (copyrighted (c) 2002-2006 ), anyone who complies with the gplv2 license terms set forth by the Free Software Foundation can freely copy, distribute and modify this document.

No commitment
This document does not guarantee the reliability of any content in this article. You must take risks for any concepts, examples, and information in your use of the text, because errors and inaccuracies may exist, it may damage your system-although it is almost impossible to have such an accident, you are still careful-the author is not responsible for this.

Contributor
In this document, I would like to thank you in alphabetical order ):
◆ Joy y goodreau <joyg (AT) us.ibm.com> her editing work.
◆ D. stimitis <stimitis (AT) idcomm.com> points out some formatting and name mangling problems, and points out some nuances of extern "C.

Feedback
Welcome to the feedback on this document! Please send your comments and comments to this email address: <aaron@isotton.com>.

TERM
dlopen API
descriptions of dlclose, dlerror, dlopen, and dlsym functions can be found on the dlopen (3) MAN manual page.
note that when we use "dlopen", it refers to the dlopen function, while "dlopen API" refers to the entire API set.
----------------------------------------------
problem
sometimes you want to load a library (and use the function) at runtime ), this often happens when you write some plug-ins or module architectures for your program.
in C language, it is easy to load a library (it is enough to call dlopen, dlsym, and dlclose), but the situation is a little complicated for C ++. Part of the difficulty of loading a C ++ library dynamically is that C ++'s name mangling (Translator's note: Some people translate it into "name destruction", which I think is still not good at translation ), another part is that the dlopen API is implemented in C language, so it does not provide an appropriate method to load classes.
before explaining how to load the C ++ library, you 'd better learn more about name mangling. I recommend that you know about it, even if you are not interested in it. This helps you understand how problems arise and how they can be solved.

Name mangling
In each c ++ Program (or library or target file), all non-static (non-static) functions appear in the binary file in the form of a symbol. These symbols are unique strings that separate functions from each other in the program, library, and target file.
In C, the symbolic name is the function name: the symbolic name of the strcpy function is "strcpy", and so on. This may be because the names of the two non-static functions must be different.
C ++ allows overloading (different functions have the same name but different parameters ), and there are many features that C does not have-such as classes, member functions, and exception descriptions-it is almost impossible to directly use function names as symbol names. To solve this problem, C ++ adopts the so-called name mangling. It blends the function name and some information (such as the number and size of parameters) into a strange symbol name that only the compiler can understand. For example, the foo after mangle may look like Foo @ 4% 6 ^, or the symbol name does not even include "foo ".
One of the problems is that the C ++ standard (currently []) does not define how a name must be mangle, so each compiler uses its own method to perform name mangling. Some compilers even change mangling between different versions.Algorithm(Especially g ++ 2. x and 3.x ). Even if you have figured out how your compiler performs mangling, you can use dlsym to call the function, but it may be limited to your current compiler, but cannot work in the next version of the compiler.

Class
Another problem with using the dlopen API is that it only supports loading functions. However, in C ++, you may need to use a class in the library, and this requires creating an instance of this class, which is not easy to do.

Solution

Extern "C"
C ++ has a specific keyword used to declare the function using C binding: extern "C ". The function declared with extern "C" uses the function name as the symbol name, just like the C function. Therefore, only non-member functions can be declared as extern "c" and cannot be overloaded. Despite the many limitations, extern "C" functions are very useful because they can be dynamically loaded by dlopen like C functions. Given the extern "C" qualifier does not mean that C ++ cannot be used in functions.CodeOn the contrary, it is still a complete C ++ function that can use any c ++ features and various types of parameters.

Load Functions
In C ++, functions are loaded using dlsym, just like in C. However, this function must be declared with the extern "C" qualifier to prevent its symbolic name from being mangle.

Example 1. Load the function code:

//----------
// Main. cpp:
//----------
# Include <iostream>
# Include <dlfcn. h>

Int main (){
Using STD: cout;
Using STD: cerr;

Cout <"C ++ dlopen demo \ n ";

// open the library
cout <"Opening hello. so... \ n ";
void * handle = dlopen (". /Hello. so ", rtld_lazy);
If (! Handle) {
cerr <"cannot open Library:" return 1;
}< br>
// load the symbol
cout <"loading symbol hello... \ n ";
typedef void (* hello_t) ();

// Reset errors
Dlerror ();
Hello_t Hello = (hello_t) dlsym (handle, "hello ");
Const char * dlsym_error = dlerror ();
If (dlsym_error ){
Cerr <"cannot load symbol 'hello':" <dlsym_error <
'\ N ';
Dlclose (handle );
Return 1;
}

// Use it to do the calculation
Cout <"calling hello... \ n ";
Hello ();

// Close the library
Cout <"Closing library... \ n ";
Dlclose (handle );
}

//----------
// Hello. cpp:
//----------
# Include <iostream>

Extern "C" Void Hello (){
STD: cout <"hello" <'\ n ';
}

In hello. CPP, the hello function is defined as extern "C ". It is called by dlsym in Main. cpp. The function must be limited by extern "C"; otherwise, the symbol name is unknown.
Warning:
Extern "C" can be declared in two ways: the inline format used in the preceding example extern "C ", still use the extern "C" {...} in curly brackets "{...} this. The first inline form Declaration has two meanings: the external link (extern linkage) and the C language link (Language linkage), while the second method only affects the language link.
The following two statements are equivalent: code:

Extern "C" int Foo;
Extern "C" Void bar ();

And code:

Extern "C "{
Extern int Foo;
Extern void bar ();
}

For functions, the declaration of the extern and non-extern functions is no different, but the variables are different. If you declare variables, remember: code:

Extern "C" int Foo;

And code:

Extern "C "{
Int Foo;
}

It is a different thing (Translator's note: in short, the former is a declaration, while the latter is not only a declaration, but also a definition ).
For further explanations, refer to [7.5], 7th, especially section; or refer to [str2000], 9.2.4. Before you use the extern variable to search for victory, read the documents listed in the "Others" section.

Load class
Loading a class is a bit difficult, because we need an instance of the class, not just a function pointer. We cannot use new to create a class instance, because the class is not defined in the executable file, and (sometimes) We don't even know its name.
Solution: Exploitation of polymorphism! In the executable file, we define an interface base class with virtual member functions, and define a derived implementation class in the module. Generally, the interface class is abstract (if a class contains virtual functions, it is abstract ).
Dynamic Loading classes are often used to implement plug-ins, which means that a clearly defined interface must be provided-we will define an interface class and a derived implementation class.
Next, in the module, we will define two additional helper functions, which are known as "class factory functions )". One function creates a class instance and returns its pointer. The other function is used to destroy the pointer. Both functions are limited by extern "C.
To use the classes in the module, we use dlsym to load the two functions as in Example 1 with the hello function, and then we can create and destroy instances as needed.

Example 2. Load a class
We use a general polygon class as the interface, and inherit its triangle class (Translator's note: Positive triangle class) as the implementation. Code:

//----------
// Main. cpp:
//----------
# Include "polygon. HPP"
# Include <iostream>
# Include <dlfcn. h>

Int main (){
Using STD: cout;
Using STD: cerr;

// Load the triangle Library
Void * triangle = dlopen ("./triangle. So", rtld_lazy );
If (! Triangle ){
Cerr <"cannot load Library:" <dlerror () <'\ n ';
Return 1;
}

// Reset errors
Dlerror ();

// Load the symbols
Create_t * create_triangle = (create_t *) dlsym (triangle, "CREATE ");
Const char * dlsym_error = dlerror ();
If (dlsym_error ){
Cerr <"cannot load symbol create:" <dlsym_error <'\ n ';
Return 1;
}

Destroy_t * destroy_triangle = (destroy_t *) dlsym (triangle, "Destroy ");
Dlsym_error = dlerror ();
If (dlsym_error ){
Cerr <"cannot load symbol destroy:" <dlsym_error <'\ n ';
Return 1;
}

// Create an instance of the class
Polygon * poly = create_triangle ();

// Use the class
Poly-> set_side_length (7 );
Cout <"the area is:" <poly-> area () <'\ n ';

// Destroy the class
Destroy_triangle (poly );

// Unload the triangle Library
Dlclose (triangle );
}

//----------
// Polygon. HPP:
//----------
# Ifndef polygon_hpp
# Define polygon_hpp

Class polygon {
Protected:
Double side_length _;

Public:
Polygon ()
: Side_length _ (0 ){}

Virtual ~ Polygon (){}

Void set_side_length (double side_length ){
Side_length _ = side_length;
}

Virtual double area () const = 0;
};

// The types of the class factories
Typedef polygon * create_t ();
Typedef void destroy_t (polygon *);

# Endif

//----------
// Triangle. cpp:
//----------
# Include "polygon. HPP"
# Include <cmath>

Class triangle: Public polygon {
Public:
Virtual double area () const {
Return side_length _ * SQRT (3)/2;
}
};

// The class factories
Extern "C" polygon * Create (){
Return new triangle;
}

Extern "C" Void destroy (polygon * P ){
Delete P;
}

Note the following when loading a class:
◆ You must provide both a creation function and a destruction function in a module or shared library, and cannot use Delete to destroy instances within the execution file, the destroy function that can only pass the instance pointer to the module for processing. This is because in C ++, the new operator can be overloaded; this can easily lead to mismatched calls of New-delete, resulting in inexplicable memory leaks and segment errors. This is also true when linking modules and executable files with different standard libraries.
◆ The destructor of the interface class must be virtual in all circumstances ). Even if the error may be extremely small, it is almost worrying, but it is still not worth taking the risk. The extra overhead is negligible. If the base class does not require destructor, define an empty (but virtual) destructor. Otherwise, you will encounter problems sooner or later. I promise you. You can learn more about this issue in section 20th of the comp. Lang. c ++ FAQ (http://www.parashift.com/c++-faq-lite.

Source code
You can download all the code packages included in this document: http://www.isotton.com/howtos/C++-dl...xamples.tar.gz

FAQ
(Translator's note: the translation below is omitted for the time being)
1. I'm using Windows and I can't find the dlfcn. h header file! What's the problem?

The problem is that Windows doesn' t have the dlopen API, and thus there is no dlfcn. h header. there is a similar API around the loadlibrary function, and most of what is written here applies to it, too. please refer to the Microsoft Developer Network website for more information.

2. Is there some kind of dlopen-compatible wrapper for the Windows loadlibrary API?

I don't know of any, and I don't think there'll ever be one supporting all of dlopen's options.

There are alternatives though: libtltdl (a part of libtool), which wraps a variety of different dynamic loading APIs, among others dlopen and loadlibrary. another one is the dynamic module loading functionality of glib. you can use one of these to ensure better possible cross-platform compatibility. I 've never used any of them, so I can't tell you how stable they are and whether they really work.

You shoshould also read section 4, "Dynamically Loaded (DL) Libraries", of the program library howto for more techniques to load libraries and create classes independently of your platform.

Others

* The dlopen (3) man page. It explains the purpose and the use of the dlopen API.
* The article dynamic class loading for C ++ on Linux by James Norton published on the Linux journal.
* Your favorite C ++ reference about extern "C", inheritance, virtual functions, new and delete. I recommend [str2000].
* [2011-0882]
* The Program Library howto, which tells you most things you'll ever need about static, shared and Dynamically Loaded libraries and how to create them. Highly recommended.
* The Linux GCC howto to learn more about how to create libraries with GCC.

bibliography
[14482] ISO/IEC 1998--The C ++ programming language. available as PDF and as printed books from http://webstore.ansi.org /.
[str2000] stroustrupbjarne the C ++ programming language, special edition. ISBN 0-201-70073-5. addison-Wesley

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.