|
Main Page
Class Hierarchy
Alphabetical List
Compound List
File List
Compound Members
|
00001 /********************************************************************************
00002 * *
00003 * Dynamically linked library loader (DLL loader) *
00004 * *
00005 *********************************************************************************
00006 * Copyright (C) 2003 by Mathew Robertson. All Rights Reserved. *
00007 *********************************************************************************
00008 * This library is free software; you can redistribute it and/or *
00009 * modify it under the terms of the GNU Lesser General Public *
00010 * License as published by the Free Software Foundation; either *
00011 * version 2.1 of the License, or (at your option) any later version. *
00012 * *
00013 * This library is distributed in the hope that it will be useful, *
00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
00016 * Lesser General Public License for more details. *
00017 * *
00018 * You should have received a copy of the GNU Lesser General Public *
00019 * License along with this library; if not, write to the Free Software *
00020 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
00021 ********************************************************************************/
00022 #ifndef FXDLL_H
00023 #define FXDLL_H
00024
00025 namespace FXEX {
00026
00027 /**
00028 * Dynamically linked library loader which loads the library, based on the filename.
00029 * Includes a macro so as to make dynamic loading of classes simpler than would be otherwise.
00030 *
00031 * Notes:
00032 * When dynamically loading a dll, most OS's automatically load a default library function if
00033 * it it exists (DllMain on Win32, _init on Linux). The problem is two-fold in that
00034 * a) they are different names for different platforms, b) they are only called once, even
00035 * if they opened a second time, for a second thread (this is a particularly nasty problem
00036 * since the second thread wont initialise and thread specific variables).
00037 *
00038 * To combat this, I have written the class so that if your library contains a C function
00039 * FXDLL_load, it will be called the first time a library is loaded (for a given FXDLL object),
00040 * thus solving the platform problem. Also, if you load it from a second thread (and thus from
00041 * a second FXDLL objects), it calls FXDLL_load in that thread too (the OS specific auto-exec
00042 * functions dont do this), thus correctly initialising thread specific variables.
00043 *
00044 * Conversly, when you unload the library, if you have a library function called FXDLL_unload,
00045 * it is called before unloading the library (for each FXDLL instance).
00046 */
00047 class FXAPI FXDLL {
00048 protected:
00049 FXString file;
00050 FXString loadedFile;
00051 FXDLLHandle handle;
00052 FXuint refcount;
00053
00054 protected:
00055 virtual FXDLLHandle loadLibrary(const FXString& filename);
00056 virtual FXDLLHandle unloadLibrary();
00057
00058 public:
00059 /// create a dll object, using specified filename
00060 FXDLL(const FXString& filename="");
00061
00062 /// set to new filename - fails silently if library is already loaded.
00063 void setFilename(const FXString& filename);
00064
00065 /// get the filename
00066 FXString getFilename() const { return file; }
00067
00068 /// get the name of the file actually loaded
00069 FXString getLoadedFilename() const { return loadedFile; }
00070
00071 /// open library file
00072 FXbool open();
00073
00074 /// close library
00075 void close();
00076
00077 /// indicates if the library is already open
00078 FXbool isOpen();
00079
00080 /// get handle
00081 FXDLLHandle getHandle() { return handle; }
00082
00083 /**
00084 * return a pointer to a function
00085 * you will need to do something like this:
00086 *
00087 * double (*calc)(double a,double b);
00088 * calc = dll.getFunction("power");
00089 * result = (*calc)(val1,val2);
00090 */
00091 virtual void* getFunction(const FXString& function);
00092
00093 /// close library
00094 virtual ~FXDLL();
00095 };
00096
00097
00098 /**
00099 * A helper routine for implementing dynamic method loading within a class.
00100 * This implementation uses the method parameters: (FXint,void*) or ()
00101 *
00102 * eg:
00103 * FXDLL_METHOD(FXint,libraryMethod,(void *data,FXint size),const);
00104 * or:
00105 * FXDLL_METHOD(FXString,libraryMethod,(),);
00106 */
00107 #define FXDLL_METHOD(returntype,funcname,params,constness) \
00108 typedef returntype (CALLBACK* functype_##funcname) params constness; \
00109 functype_##funcname dll_##funcname=NULL; \
00110 FXbool isLoaded_##funcname=FALSE;\
00111 returntype funcname params { \
00112 if (!getHandle()) return (returntype)NULL; \
00113 if (!isLoaded_##funcname) { \
00114 dll_##funcname= (functype_##funcname)getFunction(#funcname); \
00115 if (dll_##funcname == NULL) return (returntype)NULL; \
00116 isLoaded_##funcname = TRUE;\
00117 } \
00118 return (dll_##funcname)(params); \
00119 }
00120
00121
00122 /**
00123 * A helper routine for implementing dynamic function loading.
00124 * This implementation uses the function parameters : (FXint,void*) or ()
00125 *
00126 * eg:
00127 * FXDLL_FUNCTION(dllp,FXint,libraryFunction,(void *data,FXint size),const);
00128 * or:
00129 * FXDLL_FUNCTION(pointer_to_FXDLL,FXbool,libraryFunction,(FXString s),);
00130 */
00131 #define FXDLL_FUNCTION(fxdllpointer,returntype,funcname,params,constness) \
00132 typedef returntype (CALLBACK* functype_##funcname) params constness; \
00133 functype_##funcname dll_##funcname=NULL; \
00134 FXbool isLoaded_##funcname=FALSE;\
00135 returntype funcname params { \
00136 if (!fxdllpointer->getHandle()) return (returntype)NULL; \
00137 if (!isLoaded_##funcname) { \
00138 dll_##funcname= (functype_##funcname)fxdllpointer->getFunction(#funcname); \
00139 if (dll_##funcname == NULL) return (returntype)NULL; \
00140 isLoaded_##funcname = TRUE;\
00141 } \
00142 return (dll_##funcname)(params); \
00143 }
00144
00145 } // namespace FXEX
00146 #endif // FXDLL_H
00147