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