/////////////////////////////////////////////////////////////////////////////
-// Name: dynlib.cpp
+// Name: src/common/dynlib.cpp
// Purpose: Dynamic library management
// Author: Guilhem Lavaux
// Modified by:
// Created: 20/07/98
// RCS-ID: $Id$
-// Copyright: (c) Guilhem Lavaux
+// Copyright: (c) 1998 Guilhem Lavaux
+// 2000-2005 Vadim Zeitlin
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
+//FIXME: This class isn't really common at all, it should be moved into
+// platform dependent files (already done for Windows and Unix)
+
// ============================================================================
// declarations
// ============================================================================
// headers
// ----------------------------------------------------------------------------
-#ifdef __GNUG__
-# pragma implementation "dynlib.h"
-#endif
-
#include "wx/wxprec.h"
#ifdef __BORLANDC__
- #pragma hdrstop
+ #pragma hdrstop
#endif
#if wxUSE_DYNLIB_CLASS
-#if defined(__WINDOWS__)
- #include "wx/msw/private.h"
-#endif
-
#include "wx/dynlib.h"
+
+#ifndef WX_PRECOMP
+ #include "wx/intl.h"
+ #include "wx/log.h"
+ #include "wx/app.h"
+ #include "wx/utils.h"
+#endif //WX_PRECOMP
+
#include "wx/filefn.h"
-#include "wx/intl.h"
-#include "wx/log.h"
-#include "wx/utils.h"
#include "wx/filename.h" // for SplitPath()
+#include "wx/platinfo.h"
-#if defined(__WXMAC__)
- #include "wx/mac/private.h"
-#endif
+#include "wx/arrimpl.cpp"
+WX_DEFINE_USER_EXPORTED_OBJARRAY(wxDynamicLibraryDetailsArray)
// ============================================================================
// implementation
// ============================================================================
-#if defined(__DARWIN__)
-// ---------------------------------------------------------------------------
-// For Darwin/Mac OS X
-// supply the sun style dlopen functions in terms of Darwin NS*
-// ---------------------------------------------------------------------------
-
-/* Porting notes:
- * The dlopen port is a port from dl_next.xs by Anno Siegel.
- * dl_next.xs is itself a port from dl_dlopen.xs by Paul Marquess.
- * The method used here is just to supply the sun style dlopen etc.
- * functions in terms of Darwin NS*.
- */
-
-#include <stdio.h>
-#include <mach-o/dyld.h>
-
-static char dl_last_error[1024];
-
-static
-void TranslateError(const char *path, int number)
-{
- unsigned int index;
- static char *OFIErrorStrings[] =
- {
- "%s(%d): Object Image Load Failure\n",
- "%s(%d): Object Image Load Success\n",
- "%s(%d): Not an recognisable object file\n",
- "%s(%d): No valid architecture\n",
- "%s(%d): Object image has an invalid format\n",
- "%s(%d): Invalid access (permissions?)\n",
- "%s(%d): Unknown error code from NSCreateObjectFileImageFromFile\n",
- };
-#define NUM_OFI_ERRORS (sizeof(OFIErrorStrings) / sizeof(OFIErrorStrings[0]))
-
- index = number;
- if (index > NUM_OFI_ERRORS - 1) {
- index = NUM_OFI_ERRORS - 1;
- }
- sprintf(dl_last_error, OFIErrorStrings[index], path, number);
-}
-
-const char *dlerror()
-{
- return dl_last_error;
-}
-
-void *dlopen(const char *path, int WXUNUSED(mode) /* mode is ignored */)
-{
- int dyld_result;
- NSObjectFileImage ofile;
- NSModule handle = NULL;
-
- dyld_result = NSCreateObjectFileImageFromFile(path, &ofile);
- if (dyld_result != NSObjectFileImageSuccess)
- {
- TranslateError(path, dyld_result);
- }
- else
- {
- // NSLinkModule will cause the run to abort on any link error's
- // not very friendly but the error recovery functionality is limited.
- handle = NSLinkModule(ofile, path, NSLINKMODULE_OPTION_BINDNOW);
- }
-
- return handle;
-}
-
-int dlclose(void *handle)
-{
- NSUnLinkModule( handle, NSUNLINKMODULE_OPTION_NONE);
- return 0;
-}
-
-void *dlsym(void *handle, const char *symbol)
-{
- void *addr;
-
- NSSymbol nsSymbol = NSLookupSymbolInModule( handle , symbol ) ;
-
- if ( nsSymbol)
- {
- addr = NSAddressOfSymbol(nsSymbol);
- }
- else
- {
- addr = NULL;
- }
- return addr;
-}
-
-#endif // defined(__DARWIN__)
-
-
// ---------------------------------------------------------------------------
// wxDynamicLibrary
// ---------------------------------------------------------------------------
-//FIXME: This class isn't really common at all, it should be moved into
-// platform dependent files.
-
-#if defined(__WINDOWS__) || defined(__WXPM__) || defined(__EMX__)
- const wxChar *wxDynamicLibrary::ms_dllext = _T(".dll");
-#elif defined(__UNIX__)
- #if defined(__HPUX__)
- const wxChar *wxDynamicLibrary::ms_dllext = _T(".sl");
- #else
- const wxChar *wxDynamicLibrary::ms_dllext = _T(".so");
- #endif
+#if defined(__WXPM__) || defined(__EMX__)
+ const wxString wxDynamicLibrary::ms_dllext(wxT(".dll"));
#endif
+// for MSW/Unix it is defined in platform-specific file
+#if !(defined(__WINDOWS__) || defined(__UNIX__)) || defined(__EMX__)
+
wxDllType wxDynamicLibrary::GetProgramHandle()
{
-#if defined( HAVE_DLOPEN ) && !defined(__EMX__)
- return dlopen(0, RTLD_LAZY);
-#elif defined (HAVE_SHL_LOAD)
- return PROG_HANDLE;
-#else
- wxFAIL_MSG( wxT("This method is not implemented under Windows or OS/2"));
+ wxFAIL_MSG( wxT("GetProgramHandle() is not implemented under this platform"));
return 0;
-#endif
}
-bool wxDynamicLibrary::Load(wxString libname, int flags)
+#endif // __WINDOWS__ || __UNIX__
+
+
+bool wxDynamicLibrary::Load(const wxString& libnameOrig, int flags)
{
- wxASSERT_MSG(m_handle == 0, _T("Library already loaded."));
+ wxASSERT_MSG(m_handle == 0, wxT("Library already loaded."));
// add the proper extension for the DLL ourselves unless told not to
+ wxString libname = libnameOrig;
if ( !(flags & wxDL_VERBATIM) )
{
// and also check that the libname doesn't already have it
// different ways to load a shared library
//
// FIXME: should go to the platform-specific files!
-#if defined(__WXMAC__) && !defined(__DARWIN__)
- FSSpec myFSSpec;
- Ptr myMainAddr;
- Str255 myErrName;
-
- wxMacFilename2FSSpec( libname , &myFSSpec );
-
- if( GetDiskFragment( &myFSSpec,
- 0,
- kCFragGoesToEOF,
- "\p",
- kPrivateCFragCopy,
- &m_handle,
- &myMainAddr,
- myErrName ) != noErr )
- {
- p2cstr( myErrName );
- wxLogSysError( _("Failed to load shared library '%s' Error '%s'"),
- libname.c_str(),
- (char*)myErrName );
- m_handle = 0;
- }
-
-#elif defined(__WXPM__) || defined(__EMX__)
- char err[256] = "";
+#if defined(__WXPM__) || defined(__EMX__)
+ char err[256] = "";
DosLoadModule(err, sizeof(err), libname.c_str(), &m_handle);
-
-#elif defined(HAVE_DLOPEN) || defined(__DARWIN__)
-
-#if defined(__VMS) || defined(__DARWIN__)
- m_handle = dlopen(libname.c_str(), 0); // The second parameter is ignored
-#else // !__VMS && !__DARWIN__
- int rtldFlags = 0;
-
- if ( flags & wxDL_LAZY )
- {
- wxASSERT_MSG( (flags & wxDL_NOW) == 0,
- _T("wxDL_LAZY and wxDL_NOW are mutually exclusive.") );
-#ifdef RTLD_LAZY
- rtldFlags |= RTLD_LAZY;
-#else
- wxLogDebug(_T("wxDL_LAZY is not supported on this platform"));
-#endif
- }
- else if ( flags & wxDL_NOW )
- {
-#ifdef RTLD_NOW
- rtldFlags |= RTLD_NOW;
-#else
- wxLogDebug(_T("wxDL_NOW is not supported on this platform"));
+#else // this should be the only remaining branch eventually
+ m_handle = RawLoad(libname, flags);
#endif
- }
- if ( flags & wxDL_GLOBAL )
+ if ( m_handle == 0 && !(flags & wxDL_QUIET) )
{
-#ifdef RTLD_GLOBAL
- rtldFlags |= RTLD_GLOBAL;
-#else
- wxLogDebug(_T("RTLD_GLOBAL is not supported on this platform."));
-#endif
- }
-
- m_handle = dlopen(libname.fn_str(), rtldFlags);
-#endif // __VMS || __DARWIN__ ?
-
-#elif defined(HAVE_SHL_LOAD)
- int shlFlags = 0;
-
- if( flags & wxDL_LAZY )
- {
- wxASSERT_MSG( (flags & wxDL_NOW) == 0,
- _T("wxDL_LAZY and wxDL_NOW are mutually exclusive.") );
- shlFlags |= BIND_DEFERRED;
- }
- else if( flags & wxDL_NOW )
- {
- shlFlags |= BIND_IMMEDIATE;
- }
- m_handle = shl_load(libname.fn_str(), BIND_DEFERRED, 0);
-
-#elif defined(__WINDOWS__)
- m_handle = ::LoadLibrary(libname.c_str());
-#else
- #error "runtime shared lib support not implemented on this platform"
-#endif
-
- if ( m_handle == 0 )
- {
- wxString msg(_("Failed to load shared library '%s'"));
-#if defined(HAVE_DLERROR) && !defined(__EMX__)
-
-#if wxUSE_UNICODE
- wxWCharBuffer buffer = wxConvLocal.cMB2WC( dlerror() );
- const wxChar *err = buffer;
+#ifdef wxHAVE_DYNLIB_ERROR
+ Error();
#else
- const wxChar *err = dlerror();
-#endif
-
- if( err )
- wxLogError( msg, err );
-#else
- wxLogSysError( msg, libname.c_str() );
+ wxLogSysError(_("Failed to load shared library '%s'"), libname.c_str());
#endif
}
return IsLoaded();
}
-void wxDynamicLibrary::Unload()
+// for MSW and Unix this is implemented in the platform-specific file
+//
+// TODO: move the rest to os2/dlpm.cpp and mac/dlmac.cpp!
+#if (!defined(__WINDOWS__) && !defined(__UNIX__)) || defined(__EMX__)
+
+/* static */
+void wxDynamicLibrary::Unload(wxDllType handle)
{
- if( IsLoaded() )
- {
-#if defined(__WXPM__) || defined(__EMX__)
- DosFreeModule( m_handle );
-#elif defined(HAVE_DLOPEN) || defined(__DARWIN__)
- dlclose( m_handle );
-#elif defined(HAVE_SHL_LOAD)
- shl_unload( m_handle );
-#elif defined(__WINDOWS__)
- ::FreeLibrary( m_handle );
-#elif defined(__WXMAC__) && !defined(__DARWIN__)
- CloseConnection( (CFragConnectionID*) &m_handle );
+#if defined(__OS2__) || defined(__EMX__)
+ DosFreeModule( handle );
#else
-#error "runtime shared lib support not implemented"
+ #error "runtime shared lib support not implemented"
#endif
- m_handle = 0;
- }
}
-void *wxDynamicLibrary::GetSymbol(const wxString &name, bool *success) const
+#endif // !(__WINDOWS__ || __UNIX__)
+
+void *wxDynamicLibrary::DoGetSymbol(const wxString &name, bool *success) const
{
wxCHECK_MSG( IsLoaded(), NULL,
- _T("Can't load symbol from unloaded library") );
+ wxT("Can't load symbol from unloaded library") );
- bool failed = FALSE;
void *symbol = 0;
-#if defined(__WXMAC__) && !defined(__DARWIN__)
- Ptr symAddress;
- CFragSymbolClass symClass;
- Str255 symName;
-#if TARGET_CARBON
- c2pstrcpy( (StringPtr) symName, name );
+ wxUnusedVar(symbol);
+#if defined(__WXPM__) || defined(__EMX__)
+ DosQueryProcAddr( m_handle, 1L, name.c_str(), (PFN*)symbol );
#else
- strcpy( (char *)symName, name );
- c2pstr( (char *)symName );
+ symbol = RawGetSymbol(m_handle, name);
#endif
- if( FindSymbol( dllHandle, symName, &symAddress, &symClass ) == noErr )
- symbol = (void *)symAddress;
-
-#elif defined(__WXPM__) || defined(__EMX__)
- DosQueryProcAddr( m_handle, 1L, name.c_str(), (PFN*)symbol );
-#elif defined(HAVE_DLOPEN) || defined(__DARWIN__)
- symbol = dlsym( m_handle, name.fn_str() );
+ if ( success )
+ *success = symbol != NULL;
-#elif defined(HAVE_SHL_LOAD)
- // use local variable since shl_findsym modifies the handle argument
- // to indicate where the symbol was found (GD)
- wxDllType the_handle = m_handle;
- if( shl_findsym( &the_handle, name.fn_str(), TYPE_UNDEFINED, &symbol ) != 0 )
- symbol = 0;
-
-#elif defined(__WINDOWS__)
- symbol = (void*) ::GetProcAddress( m_handle, name.mb_str() );
-
-#else
-#error "runtime shared lib support not implemented"
-#endif
+ return symbol;
+}
+void *wxDynamicLibrary::GetSymbol(const wxString& name, bool *success) const
+{
+ void *symbol = DoGetSymbol(name, success);
if ( !symbol )
{
-#if defined(HAVE_DLERROR) && !defined(__EMX__)
-
-#if wxUSE_UNICODE
- wxWCharBuffer buffer = wxConvLocal.cMB2WC( dlerror() );
- const wxChar *err = buffer;
+#ifdef wxHAVE_DYNLIB_ERROR
+ Error();
#else
- const wxChar *err = dlerror();
-#endif
-
- if( err )
- {
- wxLogError(wxT("%s"), err);
- }
-#else
- failed = TRUE;
wxLogSysError(_("Couldn't find symbol '%s' in a dynamic library"),
name.c_str());
#endif
}
- if( success )
- *success = !failed;
return symbol;
}
-
+
+// ----------------------------------------------------------------------------
+// informational methods
+// ----------------------------------------------------------------------------
/*static*/
-wxString wxDynamicLibrary::CanonicalizeName(const wxString& name,
- wxDynamicLibraryCategory cat)
+wxString
+wxDynamicLibrary::CanonicalizeName(const wxString& name,
+ wxDynamicLibraryCategory cat)
{
-#ifdef __UNIX__
- if ( cat == wxDL_MODULE )
- return name + GetDllExt();
- else
- return wxString(_T("lib")) + name + GetDllExt();
-#else
- return name + GetDllExt();
-#endif
+ wxString nameCanonic;
+
+ // under Unix the library names usually start with "lib" prefix, add it
+#if defined(__UNIX__) && !defined(__EMX__)
+ switch ( cat )
+ {
+ default:
+ wxFAIL_MSG( wxT("unknown wxDynamicLibraryCategory value") );
+ // fall through
+
+ case wxDL_MODULE:
+ // don't do anything for modules, their names are arbitrary
+ break;
+
+ case wxDL_LIBRARY:
+ // library names should start with "lib" under Unix
+ nameCanonic = wxT("lib");
+ break;
+ }
+#else // !__UNIX__
+ wxUnusedVar(cat);
+#endif // __UNIX__/!__UNIX__
+
+ nameCanonic << name << GetDllExt();
+ return nameCanonic;
}
/*static*/
wxString suffix;
if ( cat == wxDL_PLUGIN_GUI )
{
- suffix = wxString::FromAscii(
-#if defined(__WXMSW__)
- "msw"
-#elif defined(__WXGTK__)
- "gtk"
-#elif defined(__WXMGL__)
- "mgl"
-#elif defined(__WXMOTIF__)
- "motif"
-#elif defined(__WXOS2__)
- "pm"
-#elif defined(__WXX11__)
- "x11"
-#elif defined(__WXMAC__)
- "mac"
-#elif defined(__WXCOCOA__)
- "cocoa"
-#else // FIXME - wrong!
- ""
-#endif
- );
-
-#ifdef __WXUNIVERSAL__
- suffix << _T("univ");
-#endif
+ suffix = wxPlatformInfo::Get().GetPortIdShortName();
}
#if wxUSE_UNICODE
- suffix << _T('u');
+ suffix << wxT('u');
#endif
#ifdef __WXDEBUG__
- suffix << _T('d');
+ suffix << wxT('d');
#endif
if ( !suffix.empty() )
- suffix = wxString(_T("_")) + suffix;
+ suffix = wxString(wxT("_")) + suffix;
-#ifdef __UNIX__
+#define WXSTRINGIZE(x) #x
+#if defined(__UNIX__) && !defined(__EMX__)
#if (wxMINOR_VERSION % 2) == 0
- #define wxDLLVER(x,y,z) "-" #x "." #y
+ #define wxDLLVER(x,y,z) "-" WXSTRINGIZE(x) "." WXSTRINGIZE(y)
#else
- #define wxDLLVER(x,y,z) "-" #x "." #y "." #z
+ #define wxDLLVER(x,y,z) "-" WXSTRINGIZE(x) "." WXSTRINGIZE(y) "." WXSTRINGIZE(z)
#endif
#else
#if (wxMINOR_VERSION % 2) == 0
- #define wxDLLVER(x,y,z) #x #y
+ #define wxDLLVER(x,y,z) WXSTRINGIZE(x) WXSTRINGIZE(y)
#else
- #define wxDLLVER(x,y,z) #x #y #z
+ #define wxDLLVER(x,y,z) WXSTRINGIZE(x) WXSTRINGIZE(y) WXSTRINGIZE(z)
#endif
#endif
+
suffix << wxString::FromAscii(wxDLLVER(wxMAJOR_VERSION, wxMINOR_VERSION,
wxRELEASE_NUMBER));
#undef wxDLLVER
+#undef WXSTRINGIZE
+
+#ifdef __WINDOWS__
+ // Add compiler identification:
+ #if defined(__GNUG__)
+ suffix << wxT("_gcc");
+ #elif defined(__VISUALC__)
+ suffix << wxT("_vc");
+ #elif defined(__WATCOMC__)
+ suffix << wxT("_wat");
+ #elif defined(__BORLANDC__)
+ suffix << wxT("_bcc");
+ #endif
+#endif
return CanonicalizeName(name + suffix, wxDL_MODULE);
}
-
+
/*static*/
wxString wxDynamicLibrary::GetPluginsDirectory()
{
#ifdef __UNIX__
wxString format = wxGetInstallPrefix();
+ wxString dir;
format << wxFILE_SEP_PATH
<< wxT("lib") << wxFILE_SEP_PATH
<< wxT("wx") << wxFILE_SEP_PATH
+#if (wxMINOR_VERSION % 2) == 0
<< wxT("%i.%i");
- wxString dir;
dir.Printf(format.c_str(), wxMAJOR_VERSION, wxMINOR_VERSION);
- return dir;
#else
+ << wxT("%i.%i.%i");
+ dir.Printf(format.c_str(),
+ wxMAJOR_VERSION, wxMINOR_VERSION, wxRELEASE_NUMBER);
+#endif
+ return dir;
+
+#else // ! __UNIX__
return wxEmptyString;
#endif
}