summaryrefslogtreecommitdiff
path: root/3rdparty/plibsys/src/plibraryloader.h
blob: d44bef2f702fdec21d122becde4d31f44b6d6990 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*
 * The MIT License
 *
 * Copyright (C) 2015-2017 Alexander Saprykin <saprykin.spb@gmail.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * 'Software'), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * @file plibraryloader.h
 * @brief Shared library loader
 * @author Alexander Saprykin
 *
 * All modern operating systems support dynamic loadable objects. Such objects
 * are compiled with special flags and can be loaded by other programs and
 * libraries later at the runtime. These loadable objects often called as the
 * shared libraries, though some platforms even allow to treat the program
 * binary as a loadable object, too.
 *
 * When the program is linked with a shared library its dependency would be
 * resolved by the operating system automatically before starting the program.
 * But in some circumstances you may need to load a shared library object
 * explicitly (i.e. implementing a plugin subsystem, checking for API
 * availability).
 *
 * All functions and variables which a shared library is exporting are called
 * symbols. Usually only the exported symbols are available from outside the
 * shared library. Actually all those symbols represent a library API.
 *
 * Use p_library_loader_new() to load a shared library and
 * p_library_loader_get_symbol() to retrieve a pointer to a symbol within it.
 * Close the library after usage with p_library_loader_free().
 *
 * Please note the following platform specific differences:
 *
 * - HP-UX doesn't support loading libraries containing TLS and built with
 * static TLS model. The same rule applies to any library used as dependency.
 * HP-UX on 32-bit PA-RISC systems doesn't support reference counting for loaded
 * libraries when using shl_* family of functions (always removes all library
 * references on unload).
 *
 * - On OpenVMS only shareable images (linked with /SHAREABLE) can be used for
 * dynamic symbol resolving. Usually they have .EXE extension.
 *
 * - BeOS supports dynamic loading for add-ons only. It is also possible to
 * load the same library several times independently (not like a traditional
 * shared library).
 */

#if !defined (PLIBSYS_H_INSIDE) && !defined (PLIBSYS_COMPILATION)
#  error "Header files shouldn't be included directly, consider using <plibsys.h> instead."
#endif

#ifndef PLIBSYS_HEADER_PLIBRARYLOADER_H
#define PLIBSYS_HEADER_PLIBRARYLOADER_H

#include <pmacros.h>
#include <ptypes.h>

P_BEGIN_DECLS

/** Opaque data structure to handle a shared library. */
typedef struct PLibraryLoader_ PLibraryLoader;

/** Pointer to a function address. */
typedef void (*PFuncAddr) (void);

/**
 * @brief Loads a shared library.
 * @param path Path to the shared library file.
 * @return Pointer to #PLibraryLoader in case of success, NULL otherwise.
 * @since 0.0.1
 *
 * If you are loading the already loaded shared library, an operating system
 * increments corresponding reference count and decrements it after freeing
 * #PLibraryLoader, thus the shared library would be unloaded from the address
 * space only when the counter becomes zero.
 */
P_LIB_API PLibraryLoader *	p_library_loader_new		(const pchar	*path);

/**
 * @brief Gets a pointer to a symbol in the loaded shared library.
 * @param loader Pointer to the loaded shared library handle.
 * @param sym Name of the symbol.
 * @return Pointer to the symbol in case of success, NULL otherwise.
 * @since 0.0.1
 *
 * Since the symbol may have a NULL value, the returned NULL value from this
 * call actually doesn't mean the failed result. You can additionally check the
 * error result using p_library_loader_get_last_error().
 */
P_LIB_API PFuncAddr		p_library_loader_get_symbol	(PLibraryLoader	*loader,
								 const pchar	*sym);

/**
 * @brief Frees memory and allocated resources of #PLibraryLoader.
 * @param loader #PLibraryLoader object to free.
 * @since 0.0.1
 */
P_LIB_API void			p_library_loader_free		(PLibraryLoader	*loader);

/**
 * @brief Gets the last occurred error.
 * @param loader #PLibraryLoader object to get error for.
 * @return Human readable error string in case of success, NULL otherwise.
 * @since 0.0.1
 * @version 0.0.3 @p loader parameter was added.
 * @note Caller takes ownership of the returned string.
 *
 * The NULL result may indicate that no error was occurred since the last call.
 *
 * Different operating systems have different behavior on error indicating.
 * Some systems reset an error status before the call, some do not. Some
 * systems write the successful call result (usually zero) to the error status,
 * thus resetting an error from the previous call.
 *
 * Some operating systems may return last error even if library handler was not
 * created. In that case try to pass NULL value as a parameter.
 */
P_LIB_API pchar *		p_library_loader_get_last_error	(PLibraryLoader	*loader);

/**
 * @brief Checks whether library loading subsystem uses reference counting.
 * @return TRUE in case of success, FALSE otherwise.
 * @since 0.0.3
 *
 * When reference counting is supported, the same shared library can be opened
 * several times, but it would be completely unloaded from the memory only when
 * the last reference to it is removed.
 *
 * @note For now, only HP-UX on 32-bit PA-RISC systems with shl_* model doesn't
 * support reference counting.
 */
P_LIB_API pboolean		p_library_loader_is_ref_counted (void);

P_END_DECLS

#endif /* PLIBSYS_HEADER_PLIBRARYLOADER_H */