Content deleted Content added
→Windows: this expects a LPCWSTR instead of const char * |
|||
(45 intermediate revisions by 29 users not shown) | |||
Line 1:
{{Short description|Mechanism by which a computer program can load a library (or other binary) into memory}}
{{distinguish|text=[[active load|dynamic load]]}}
{{Redirect-distinguish2|Dynamically loaded library|[[dynamic-link library|dynamically linked library]]}}
{{Use dmy dates|date=July 2019|cs1-dates=y}}
'''Dynamic loading''' is a mechanism by which a [[computer program]] can, at [[Run time (program lifecycle phase)|run time]], load a [[Library (computing)|library]]
==History==
Line 9 ⟶ 11:
* Libraries could be protected from unauthorized modification
[[IBM]]'s strategic [[transaction processing]] system, [[CICS]] (1970s onwards) uses dynamic loading extensively both for its [[
[[Shared libraries]] were added to Unix in the 1980s, but initially without the ability to let a program load additional libraries after startup.<ref name="spe"
==Uses==
Dynamic loading is most frequently used in implementing [[Plug-in (computing)|software plugins]].<ref name="autobook"
==In C/C++==
Not all systems support dynamic loading. [[
===Summary===
Line 23 ⟶ 25:
|-
! Name
! [[
! [[Windows API|Microsoft Windows API]]
|-
Line 49 ⟶ 51:
===Loading the library===
Loading the library is accomplished with <code>LoadLibrary</code> or <code>LoadLibraryEx</code> on [[Microsoft Windows|Windows]] and with <code>dlopen</code> on [[
====Most
<
void* sdl_library = dlopen("libSDL.so", RTLD_LAZY);
if (!sdl_library
// report error ...
} else {
// use the result in a call to dlsym
}
</syntaxhighlight>
====macOS====
As a [[
<
void* sdl_library = dlopen("
if (!sdl_library
// report error ...
} else {
// use the result in a call to dlsym
}
</syntaxhighlight>
As a [[Application framework|macOS Framework]]:
<
void* sdl_library = dlopen("/Library/Frameworks/SDL.framework/SDL", RTLD_LAZY);
if (!sdl_library
// report error ...
} else {
// use the result in a call to dlsym
}
</syntaxhighlight>
Or if the framework or bundle contains Objective-C code:
<
NSBundle *bundle = [NSBundle bundleWithPath:@"/Library/Plugins/Plugin.bundle"];
NSError *err = nil;
Line 97 ⟶ 99:
// Handle error.
}
</syntaxhighlight>
====Windows====
<
HMODULE sdl_library = LoadLibrary(
if (!sdl_library
// report error ...
} else {
// use the result in a call to GetProcAddress
}
</syntaxhighlight>
===Extracting library contents===
Extracting the contents of a dynamically loaded library is achieved with <code>GetProcAddress</code> on [[Microsoft Windows|Windows]] and with <code>dlsym</code> on [[
====
<
void* initializer = dlsym(sdl_library, "SDL_Init");
if (!initializer
// report error ...
} else {
// cast initializer to its proper type and use
}
</syntaxhighlight>
On macOS, when using Objective-C bundles, one can also:
<
Class rootClass = [bundle principalClass]; // Alternatively, NSClassFromString() can be used to obtain a class by name.
if (rootClass)
Line 132 ⟶ 134:
// Report error.
}
</syntaxhighlight>
====Windows====
<
FARPROC initializer = GetProcAddress(sdl_library, "SDL_Init");
if (!initializer
// report error ...
} else {
// cast initializer to its proper type and use
}
</syntaxhighlight>
===Converting
The result of <code>dlsym()</code> or <code>GetProcAddress()</code> has to be converted to a pointer of the
====Windows====
In
<
typedef INT_PTR (*FARPROC)(void);
</syntaxhighlight>
This can be problematic when the address of an object is to be retrieved rather than a function. However, usually one wants to extract functions anyway, so this is normally not a problem.
<
typedef void (*sdl_init_function_type)(void);
sdl_init_function_type init_func = (sdl_init_function_type) initializer;
</syntaxhighlight>
====
According to the POSIX specification, the result of <code>dlsym()</code> is a <code>void</code> pointer. However, a function pointer is not required to even have the same size as a data object pointer, and therefore a valid conversion between type <code>void*</code> and a pointer to a function may not be easy to implement on all platforms.
On most systems in use today, function and object pointers are ''de facto'' convertible. The following code snippet demonstrates one workaround which allows to perform the conversion anyway on many systems:
<
typedef void (*sdl_init_function_type)(void);
sdl_init_function_type init_func = (sdl_init_function_type)initializer;
</syntaxhighlight>
The above snippet will give a warning on some compilers: <code>warning: dereferencing type-punned pointer will break strict-aliasing rules</code>. Another workaround is:
<
typedef void (*sdl_init_function_type)(void);
union { sdl_init_function_type func; void
alias.obj = initializer;
sdl_init_function_type init_func = alias.func;
</syntaxhighlight>
which disables the warning even if strict aliasing is in effect. This makes use of the fact that reading from a different union member than the one most recently written to (called "[[type punning]]") is common, and explicitly allowed even if strict aliasing is in force, provided the memory is accessed through the union type directly.<ref name="gcc-strict-aliasing"
====Solving the function pointer problem on POSIX systems====
The fact remains that any conversion between function and data object pointers has to be regarded as an (inherently non-portable) implementation extension, and that no "correct" way for a direct conversion exists, since in this regard the POSIX and ISO standards contradict each other.
Because of this problem, the POSIX documentation on <code>dlsym()</code> for the outdated issue 6 stated that "a future version may either add a new function to return function pointers, or the current interface may be deprecated in favor of two new functions: one that returns data pointers and the other that returns function pointers".<ref
For the subsequent version of the standard (issue 7, 2008), the problem has been discussed and the conclusion was that function pointers have to be convertible to <code>void*</code> for POSIX compliance.<ref
If the contents of the library can be changed (i.e. in the case of a custom library), in addition to the function itself a pointer to it can be exported. Since a pointer to a function pointer is itself an object pointer, this pointer can always be legally retrieved by call to <code>dlsym()</code> and subsequent conversion. However, this approach requires maintaining separate pointers to all functions that are to be used externally, and the benefits are usually small.
===Unloading the library===
Loading a library causes memory to be allocated; the library must be deallocated in order to avoid a [[memory leak]]. Additionally, failure to unload a library can prevent [[filesystem]] operations on the [[computer file|file]] which contains the library. Unloading the library is accomplished with <code>FreeLibrary</code> on [[Microsoft Windows|Windows]] and with <code>dlclose</code> on
====
<
dlclose(sdl_library);
</syntaxhighlight>
====Windows====
<
FreeLibrary(sdl_library);
</syntaxhighlight>
===Special library===
The implementations of dynamic loading on [[
[[Microsoft Windows|Windows]] allows programmers to access symbols exported by the main executable. Windows does not use a global symbol table
====
<
void* this_process = dlopen(NULL, 0);
</syntaxhighlight>
====Windows====
<
HMODULE this_process = GetModuleHandle(NULL);
HMODULE this_process_again;
GetModuleHandleEx(0, 0, &this_process_again);
</syntaxhighlight>
==In Java==
{{further|Java
In the [[Java programming language]], [[Java class|classes]] can be dynamically loaded using the '''{{Javadoc:SE|java/lang|ClassLoader}}''' object. For example:
<
Class type = ClassLoader.getSystemClassLoader().loadClass(name);
Object obj = type.newInstance();
</syntaxhighlight>
The Reflection mechanism also provides a means to load a class if it isn't already loaded. It uses the classloader of the current class:
<
Class type = Class.forName(name);
Object obj = type.newInstance();
</syntaxhighlight>
However, there is no simple way to unload a class in a controlled way. Loaded classes can only be unloaded in a controlled way, i.e. when the programmer wants this to happen, if the classloader used to load the class is not the system class loader, and is itself unloaded. When doing so, various details need to be observed to ensure the class is really unloaded. This makes unloading of classes tedious.
Line 245 ⟶ 247:
==Platforms without dynamic loading==
Despite its promulgation in the 1980s through
==See also==
Line 259 ⟶ 261:
* [[Dynamic linker]]
* [[Dynamic-link library]]
* [[FlexOS]]<!-- might at a later stage be incorporated in the article body as example of a system supporting dynamic loading/unloading of modular subdrivers -->
* [[GNU linker]]
* [[gold (linker)]]▼
* [[Lazy loading]]
* [[Library (computing)]]
* [[Linker (computing)]]
Line 268 ⟶ 273:
* [[Relocation (computer science)]]
* [[Relocation table]]
* [[Resident System Extension]] (RSX)<!-- dynamic (but not delayed) loading/unloading of modules under CP/M-related systems -->
* [[Static library]]
* [[Terminate-and-stay-resident program]] (TSR)<!-- dynamic (but not delayed) loading of system extensions under DOS-related systenms -->
▲* [[gold (linker)]]
{{div col end}}
==References==▼
<ref name="autobook">[http://sourceware.org/autobook/autobook/autobook_158.html Autoconf, Automake, and Libtool: Dynamic Loading]</ref>
<ref name="Elf_Dynamic_Loading">{{Cite web |url=http://linux4u.jinr.ru/usoft/WWW/www_debian.org/Documentation/elf/node7.html |title=Linux4U: ELF Dynamic Loading |access-date=31 December 2007 |archive-url=https://web.archive.org/web/20110311170401/http://linux4u.jinr.ru/usoft/WWW/www_debian.org/Documentation/elf/node7.html |archive-date=11 March 2011 |url-status=dead }}</ref>
<ref name="CICS">{{Cite web |url=http://publib.boulder.ibm.com/infocenter/cicsts/v3r1/index.jsp?topic=/com.ibm.cics.ts31.doc/dfhp3/dfhp3oq.htm |title=Using the CICS-supplied procedures to install application programs}}</ref>
<ref name="CEMT">{{Cite web |url=http://www-01.ibm.com/support/docview.wss?uid=swg21031546 |title=IBM CEMT NEWCOPY or PHASEIN request fails with NOT FOR HOLD PROG - United States |date=2013-03-15}}</ref>
<ref name="spe">{{cite journal |title=An approach to genuine dynamic linking |author-first1=W. Wilson |author-last1=Ho |author-first2=Ronald A. |author-last2=Olsson |date=1991 |journal=Software: Practice and Experience |volume=21 |issue=4 |pages=375–390 |doi=10.1002/spe.4380210404 |citeseerx=10.1.1.37.933|s2cid=9422227 }}</ref>
<ref name="apache">{{Cite web |url=http://httpd.apache.org/docs/1.3/dso.html |title=Apache 1.3 Dynamic Shared Object (DSO) Support |access-date=2007-12-31 |archive-date=2011-04-22 |archive-url=https://web.archive.org/web/20110422182003/http://httpd.apache.org/docs/1.3/dso.html |url-status=dead }}</ref>
<ref name="gcc-strict-aliasing">[https://gcc.gnu.org/onlinedocs/gcc-4.3.2/gcc/Optimize-Options.html#index-fstrict_002daliasing-721 GCC 4.3.2 Optimize Options: -fstrict-aliasing]</ref>
<ref name="POSIX_dlopen">[http://www.opengroup.org/onlinepubs/009695399/functions/dlsym.html POSIX documentation on <code>dlopen()</code>] (issues 6 and 7).</ref>
<ref name="Cat-V">{{cite web |title=Dynamic Linking |url=http://harmful.cat-v.org/software/dynamic-linking/ |website=cat-v.org |publisher=9front |access-date=2014-12-22}}</ref>
<ref name="Golang">{{cite web |url=http://golang.org/doc/faq#Why_is_my_trivial_program_such_a_large_binary |title=Go FAQ}}</ref>
}}
==Further reading==
*
==External links==
* General Links
** [https://web.archive.org/web/20110311170401/http://linux4u.jinr.ru/usoft/WWW/www_debian.org/Documentation/elf/node7.html Dynamic Loading] on [[Linux4U]]
** [http://httpd.apache.org/docs/current/dso.html Dynamic Shared Object (DSO) Support] by [[Apache HTTP Server|Apache]]
** [https://web.archive.org/web/20080609064104/http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=153 C++ Dynamic Linking By Example]
** [https://github.com/danfuzz/dl-example Dynamic Library Loading Example] (complete but concise working example)
** [https://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/Conceptual/DynamicLibraries/000-Introduction/Introduction.html#//apple_ref/doc/uid/TP40001908-SW1 Dynamic Library Programming Topics from Apple Developer Connection (targeted to macOS)]
* C/C++
** [http://www.opengroup.org/onlinepubs/009695399/functions/dlopen.html dlopen]
** [http://www.opengroup.org/onlinepubs/009695399/functions/dlsym.html dlsym]
Line 288 ⟶ 310:
** [http://msdn2.microsoft.com/en-us/library/ms683212(VS.85).aspx GetProcAddress]
** [http://msdn2.microsoft.com/en-us/library/ms683152(VS.85).aspx FreeLibrary]
** [http://msdn.microsoft.com/en-us/library/151kt790.aspx Delay-Loaded DLLs]
* Java API:
** [http://java.sun.com/j2se/1.5.0/docs/api/java/lang/ClassLoader.html ClassLoader]
** [http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Class.html Class]
▲==References==
▲{{reflist|2}}
▲* The two subsections 8.1.4 "Dynamic Loading" and 8.1.5 "Dynamic Linking and shared libraries" in {{cite book | first1=Abraham |last1=Silberschatz |first2=Peter Baer |last2=Galvin |first3=Greg |last3=Gagne |title= Operating System Concepts | year=2005 |publisher=J. Wiley & Sons |isbn= 0-471-69466-5}}
{{DEFAULTSORT:Dynamic Loading}}
|