1 /******************************************************************************
2 * $Id: cplgetsymbol.cpp 13271 2007-12-06 04:44:19Z warmerdam $
3 *
4 * Project: Common Portability Library
5 * Purpose: Fetch a function pointer from a shared library / DLL.
6 * Author: Frank Warmerdam, warmerdam@pobox.com
7 *
8 ******************************************************************************
9 * Copyright (c) 1999, Frank Warmerdam
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a
12 * copy of this software and associated documentation files (the "Software"),
13 * to deal in the Software without restriction, including without limitation
14 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 * and/or sell copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included
19 * in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 * DEALINGS IN THE SOFTWARE.
28 ****************************************************************************/
29
30 #include "cpl_conv.h"
31
32 CPL_CVSID("$Id: cplgetsymbol.cpp 13271 2007-12-06 04:44:19Z warmerdam $");
33
34
35 /* ==================================================================== */
36 /* Unix Implementation */
37 /* ==================================================================== */
38 #if defined(HAVE_DLFCN_H)
39
40 #define GOT_GETSYMBOL
41
42 #include <dlfcn.h>
43
44 /************************************************************************/
45 /* CPLGetSymbol() */
46 /************************************************************************/
47
48 /**
49 * Fetch a function pointer from a shared library / DLL.
50 *
51 * This function is meant to abstract access to shared libraries and
52 * DLLs and performs functions similar to dlopen()/dlsym() on Unix and
53 * LoadLibrary() / GetProcAddress() on Windows.
54 *
55 * If no support for loading entry points from a shared library is available
56 * this function will always return NULL. Rules on when this function
57 * issues a CPLError() or not are not currently well defined, and will have
58 * to be resolved in the future.
59 *
60 * Currently CPLGetSymbol() doesn't try to:
61 * <ul>
62 * <li> prevent the reference count on the library from going up
63 * for every request, or given any opportunity to unload
64 * the library.
65 * <li> Attempt to look for the library in non-standard
66 * locations.
67 * <li> Attempt to try variations on the symbol name, like
68 * pre-prending or post-pending an underscore.
69 * </ul>
70 *
71 * Some of these issues may be worked on in the future.
72 *
73 * @param pszLibrary the name of the shared library or DLL containing
74 * the function. May contain path to file. If not system supplies search
75 * paths will be used.
76 * @param pszSymbolName the name of the function to fetch a pointer to.
77 * @return A pointer to the function if found, or NULL if the function isn't
78 * found, or the shared library can't be loaded.
79 */
80
CPLGetSymbol(const char * pszLibrary,const char * pszSymbolName)81 void *CPLGetSymbol( const char * pszLibrary, const char * pszSymbolName )
82
83 {
84 void *pLibrary;
85 void *pSymbol;
86
87 pLibrary = dlopen(pszLibrary, RTLD_LAZY);
88 if( pLibrary == NULL )
89 {
90 CPLError( CE_Failure, CPLE_AppDefined,
91 "%s", dlerror() );
92 return NULL;
93 }
94
95 pSymbol = dlsym( pLibrary, pszSymbolName );
96
97 #if (defined(__APPLE__) && defined(__MACH__))
98 /* On mach-o systems, C symbols have a leading underscore and depending
99 * on how dlcompat is configured it may or may not add the leading
100 * underscore. So if dlsym() fails add an underscore and try again.
101 */
102 if( pSymbol == NULL )
103 {
104 char withUnder[strlen(pszSymbolName) + 2];
105 withUnder[0] = '_'; withUnder[1] = 0;
106 strcat(withUnder, pszSymbolName);
107 pSymbol = dlsym( pLibrary, withUnder );
108 }
109 #endif
110
111 if( pSymbol == NULL )
112 {
113 CPLError( CE_Failure, CPLE_AppDefined,
114 "%s", dlerror() );
115 return NULL;
116 }
117
118 return( pSymbol );
119 }
120
121 #endif /* def __unix__ && defined(HAVE_DLFCN_H) */
122
123 /* ==================================================================== */
124 /* Windows Implementation */
125 /* ==================================================================== */
126 #if defined(WIN32) && !defined(WIN32CE)
127
128 #define GOT_GETSYMBOL
129
130 #include <windows.h>
131
132 /************************************************************************/
133 /* CPLGetSymbol() */
134 /************************************************************************/
135
CPLGetSymbol(const char * pszLibrary,const char * pszSymbolName)136 void *CPLGetSymbol( const char * pszLibrary, const char * pszSymbolName )
137
138 {
139 void *pLibrary;
140 void *pSymbol;
141
142 pLibrary = LoadLibrary(pszLibrary);
143 if( pLibrary == NULL )
144 {
145 LPVOID lpMsgBuf = NULL;
146 int nLastError = GetLastError();
147
148 FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER
149 | FORMAT_MESSAGE_FROM_SYSTEM
150 | FORMAT_MESSAGE_IGNORE_INSERTS,
151 NULL, nLastError,
152 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
153 (LPTSTR) &lpMsgBuf, 0, NULL );
154
155 CPLError( CE_Failure, CPLE_AppDefined,
156 "Can't load requested DLL: %s\n%d: %s",
157 pszLibrary, nLastError, (const char *) lpMsgBuf );
158 return NULL;
159 }
160
161 pSymbol = (void *) GetProcAddress( (HINSTANCE) pLibrary, pszSymbolName );
162
163 if( pSymbol == NULL )
164 {
165 CPLError( CE_Failure, CPLE_AppDefined,
166 "Can't find requested entry point: %s\n", pszSymbolName );
167 return NULL;
168 }
169
170 return( pSymbol );
171 }
172
173 #endif /* def _WIN32 */
174
175 /* ==================================================================== */
176 /* Windows CE Implementation */
177 /* ==================================================================== */
178 #if defined(WIN32CE)
179
180 #define GOT_GETSYMBOL
181
182 #include "cpl_win32ce_api.h"
183
184 /************************************************************************/
185 /* CPLGetSymbol() */
186 /************************************************************************/
187
CPLGetSymbol(const char * pszLibrary,const char * pszSymbolName)188 void *CPLGetSymbol( const char * pszLibrary, const char * pszSymbolName )
189
190 {
191 void *pLibrary;
192 void *pSymbol;
193
194 pLibrary = CE_LoadLibraryA(pszLibrary);
195 if( pLibrary == NULL )
196 {
197 CPLError( CE_Failure, CPLE_AppDefined,
198 "Can't load requested DLL: %s", pszLibrary );
199 return NULL;
200 }
201
202 pSymbol = (void *) CE_GetProcAddressA( (HINSTANCE) pLibrary, pszSymbolName );
203
204 if( pSymbol == NULL )
205 {
206 CPLError( CE_Failure, CPLE_AppDefined,
207 "Can't find requested entry point: %s\n", pszSymbolName );
208 return NULL;
209 }
210
211 return( pSymbol );
212 }
213
214 #endif /* def WIN32CE */
215
216 /* ==================================================================== */
217 /* Dummy implementation. */
218 /* ==================================================================== */
219
220 #ifndef GOT_GETSYMBOL
221
222 /************************************************************************/
223 /* CPLGetSymbol() */
224 /* */
225 /* Dummy implementation. */
226 /************************************************************************/
227
CPLGetSymbol(const char * pszLibrary,const char * pszEntryPoint)228 void *CPLGetSymbol(const char *pszLibrary, const char *pszEntryPoint)
229
230 {
231 CPLDebug( "CPL",
232 "CPLGetSymbol(%s,%s) called. Failed as this is stub"
233 " implementation.", pszLibrary, pszEntryPoint );
234 return NULL;
235 }
236 #endif
237