G:/ScriptBasic/source/dynlolib.c

Go to the documentation of this file.
00001 /* 
00002 FILE:   dynlolib.c
00003 HEADER: dynlolib.h
00004 
00005 --GNU LGPL
00006 This library is free software; you can redistribute it and/or
00007 modify it under the terms of the GNU Lesser General Public
00008 License as published by the Free Software Foundation; either
00009 version 2.1 of the License, or (at your option) any later version.
00010 
00011 This library is distributed in the hope that it will be useful,
00012 but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 Lesser General Public License for more details.
00015 
00016 You should have received a copy of the GNU Lesser General Public
00017 License along with this library; if not, write to the Free Software
00018 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 TO_HEADER:
00021 
00022 */
00023 
00024 #include <stdlib.h>
00025 #include <stdio.h>
00026 
00027 #ifdef _WIN32
00028 #include <windows.h>
00029 #include <winbase.h>
00030 #elif defined(__DARWIN__)
00031 #include <mach-o/dyld.h>
00032 #elif defined(__MACOS__)
00033 #include <string.h>
00034 #include <Files.h>
00035 #include <CodeFragments.h>
00036 #else
00037 #include <dlfcn.h>
00038 #endif
00039 
00040 /*POD
00041 @c Handling Dynamic Load Libraries
00042 
00043 The Dynamic Load Libraries are handled different on all operating systems. This file
00044 implements a common functional base handling the DLLs for ScriptBasic. All other modules
00045 of ScriptBasic that want to use DLLs should call only the functions implemented in this
00046 file.
00047 
00048 =toc
00049 
00050 CUT*/
00051 
00052 /* This is a global variable that is "violation" of thread safeness. This is
00053    used in the standalone version to ask the low level LoadLibrary function
00054    to display on the standard error debug messages when a library is not
00055    loadable. So don't worry about threads.
00056 */
00057 int GlobalDebugDisplayFlag = 0;
00058 
00059 /*POD
00060 =H dynlolib_LoadLibrary
00061 @c Load a library
00062 
00063 This function loads a library and returns a pointer that can be used in other functions
00064 referencing the loaded library.
00065 /*FUNCTION*/
00066 void *dynlolib_LoadLibrary(
00067   char *pszLibraryFile
00068   ){
00069 /*noverbatim
00070 The argument T<pszLibraryFile> is the ZCHAR file name.
00071 
00072 The file name is either absolute or relative. When a relative file name is specified the
00073 directories searched may be different on different operating systems.
00074 CUT*/
00075   char *s,*r;
00076   void *pLib;
00077 
00078 /* This code was modified in v1.0b16 to make a copy of the library string before altering \ and /
00079    This was needed, because the module loader depends on the actual file name to recognize
00080    modules already loaded. The user provided the exactly same file name for each function it declared
00081    but using forward slashes under WNT and the module loader loaded the module many times because 
00082    the stored file name was stored with the converted slash.
00083 */
00084 
00085   r = s = malloc(strlen(pszLibraryFile)+1);
00086   if( s == NULL )return NULL;
00087   strcpy(s,pszLibraryFile);
00088 
00089 #ifdef _WIN32
00090   for(  ;  *s ; s++ )
00091     if( *s == '/') *s = '\\'; /* unix file separators -> DOS */
00092   pLib = (void *)LoadLibrary(r);
00093 #elif defined(__DARWIN__)
00094   for( ;  *s ; s++ )
00095     if( *s == '\\' || *s == ':') *s = '/'; /* DOS/mac file separators -> unix */
00096 
00097   if( !_dyld_present() ){
00098     pLib = NULL;
00099     if( GlobalDebugDisplayFlag ) fprintf(stderr,"dynamic linking not available.\n");
00100     }
00101   else {
00102     pLib = (void *)NSAddImage(r, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
00103     if( pLib == NULL && GlobalDebugDisplayFlag ){
00104       NSLinkEditErrors c;
00105       int errorNumber;
00106       const char *fileName;
00107       const char *errorString;
00108       NSLinkEditError(&c,&errorNumber,&fileName,&errorString);
00109       fprintf( stderr, "%s", errorString );
00110       }
00111     }
00112 #elif defined(__MACOS__)
00113     {
00114     FSSpec fileSpec;
00115     Str255 errMsg;
00116     int err, slen;
00117     Ptr mainAddr;
00118     char *hasColon = strchr(s, ':');
00119     pLib = NULL;
00120     
00121     /* Convert to Apple string (length + nonZ chars) */
00122     slen = strlen(r);
00123     memmove( r+1, r, slen);
00124     *r=(unsigned char)slen;
00125     
00126     if( hasColon ){
00127       err = FSMakeFSSpec (0, 0, r, &fileSpec);
00128       if( err == noErr)
00129         err = GetDiskFragment (&fileSpec, 0, 0, NULL, kLoadCFrag, (CFragConnectionID *)&pLib, mainAddr, errMsg );
00130       }
00131     else
00132       err = GetSharedLibrary( r, kPowerPCCFragArch, kLoadCFrag, (CFragConnectionID *)&pLib, mainAddr, errMsg );
00133     if( err < 0 && GlobalDebugDisplayFlag )
00134       fprintf(stderr,"GetSharedLibrary error %d, message=%*s\n", err, *errMsg, errMsg+1);
00135     }
00136 #else
00137   for( ;  *s ; s++ )
00138     if( *s == '\\' || *s == ':') *s = '/'; /* DOS/mac file separators -> unix */
00139   pLib = (void *)dlopen(r,RTLD_LAZY);
00140   if( pLib == NULL && GlobalDebugDisplayFlag ){
00141     fprintf(stderr,"dlopen failed.\n");
00142     fprintf(stderr,"dlerror message=%s\n",dlerror());
00143     }
00144 #endif
00145   free(r);
00146   return pLib;
00147   }
00148 
00149 /*POD
00150 =H dynlolib_FreeLibrary
00151 @c Release a library
00152 
00153 This function releases the library that was loaded before using R<dynlolib_LoadLibrary>
00154 /*FUNCTION*/
00155 void dynlolib_FreeLibrary(
00156   void *pLibrary
00157   ){
00158 /*noverbatim
00159 The argument T<pLibrary> is the pointer, which was returned by the function R<dynlolib_LoadLibrary>
00160 CUT*/
00161 
00162 #ifdef _WIN32
00163   FreeLibrary((HMODULE)pLibrary);
00164 #elif defined(__DARWIN__)
00165   /* Can't unload a dylib on darwin */
00166 #elif defined(__MACOS__)
00167   /* CloseConnection ( (CFragConnectionID *)&pLibrary ); */
00168   /* This seems to cause the app to exit completely - probably something to do with SIOUX */
00169 #else
00170   dlclose(pLibrary);
00171 #endif
00172   return;
00173   }
00174 
00175 /*POD
00176 =H dynlolib_GetFunctionByName
00177 @c Get the entry point of a function by its name
00178 
00179 This function can be used to get the entry point of a function of a loaded module
00180 specifying the name of the function.
00181 /*FUNCTION*/
00182 void *dynlolib_GetFunctionByName(
00183   void *pLibrary,
00184   char *pszFunctionName
00185   ){
00186 /*noverbatim
00187 The argument T<pLibrary> is the pointer, which was returned by the function R<dynlolib_LoadLibrary>
00188 
00189 The argument T<pszFunctionName> is the ZCAR function name.
00190 CUT*/
00191 
00192 #ifdef _WIN32
00193   return GetProcAddress((HMODULE)pLibrary,pszFunctionName);
00194 #elif defined(__DARWIN__)
00195   char *fnName;
00196   NSSymbol sym;
00197   
00198   fnName = malloc(strlen(pszFunctionName)+2); /* C functions have underscore pre-appended */
00199   if( fnName==NULL ) return NULL;
00200   strcpy(fnName+1,pszFunctionName);
00201   *fnName = '_';
00202   
00203   sym = NSLookupSymbolInImage((struct mach_header *)pLibrary, fnName, 
00204           NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
00205   free(fnName);
00206   if( !sym ) {
00207     if( GlobalDebugDisplayFlag ){
00208       NSLinkEditErrors c;
00209       int errorNumber;
00210       const char *fileName;
00211       const char *errorString;
00212       NSLinkEditError(&c,&errorNumber,&fileName,&errorString);
00213       fprintf( stderr, "%s", errorString );
00214       }
00215     return NULL;
00216     }
00217   return NSAddressOfSymbol(sym);
00218 #elif defined(__MACOS__)
00219   {
00220   Str255 str255;
00221   void *symAdr = NULL;
00222   CFragSymbolClass symClass;
00223   int err;
00224   
00225   /* Convert to Apple string (length + nonZ chars) */
00226   *str255 = (unsigned char)strlen(pszFunctionName);
00227   memcpy( str255+1, pszFunctionName, *str255 );
00228   
00229   err = FindSymbol( (CFragConnectionID)pLibrary, str255, &symAdr, &symClass );
00230   if( err < 0 && GlobalDebugDisplayFlag )
00231     fprintf(stderr,"FindSymbol error %d: %s\n", err, pszFunctionName);
00232   return symAdr;
00233   }
00234 #else
00235   return dlsym(pLibrary,pszFunctionName);
00236 #endif
00237   }

Generated on Sun Mar 12 23:56:27 2006 for ScriptBasic by  doxygen 1.4.6-NO