2008-12-08 05:30:24 +00:00
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <string.h>
#ifdef _WIN32
#include <windows.h>
#else
#include <dlfcn.h>
#include <stdio.h>
#endif
#include "Common.h"
2008-12-25 15:56:36 +00:00
#include "FileUtil.h"
2008-12-08 05:30:24 +00:00
#include "StringUtil.h"
#include "DynamicLibrary.h"
DynamicLibrary :: DynamicLibrary ()
{
library = 0 ;
}
std :: string GetLastErrorAsString ()
{
2008-12-17 15:34:27 +00:00
#ifdef _WIN32
2008-12-25 15:56:36 +00:00
LPVOID lpMsgBuf = 0 ;
2008-12-08 05:30:24 +00:00
DWORD error = GetLastError ();
FormatMessage (
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM ,
NULL ,
error ,
MAKELANGID ( LANG_NEUTRAL , SUBLANG_DEFAULT ), // Default language
( LPTSTR ) & lpMsgBuf ,
0 , NULL );
std :: string s ;
if ( lpMsgBuf )
{
s = (( char * ) lpMsgBuf );
LocalFree ( lpMsgBuf );
} else {
s = StringFromFormat ( "(unknown error %08x)" , error );
}
return s ;
2008-12-17 15:34:27 +00:00
#else
static std :: string errstr ;
char * tmp = dlerror ();
if ( tmp )
errstr = tmp ;
return errstr ;
2008-12-08 05:30:24 +00:00
#endif
2008-12-17 16:24:03 +00:00
}
2008-12-25 15:56:36 +00:00
// Loading means loading the dll with LoadLibrary() to get an instance to the dll.
// This is done when Dolphin is started to determine which dlls are good, and
// before opening the Config and Debugging windows from Plugin.cpp and
// before opening the dll for running the emulation in Video_...cpp in Core.
// Since this is fairly slow, TODO: think about implementing some sort of cache.
2008-12-08 05:30:24 +00:00
int DynamicLibrary :: Load ( const char * filename )
{
if ( ! filename || strlen ( filename ) == 0 )
{
LOG ( MASTER_LOG , "Missing filename of dynamic library to load" );
2008-12-17 15:34:27 +00:00
PanicAlert ( "Missing filename of dynamic library to load" );
2008-12-08 05:30:24 +00:00
return 0 ;
}
LOG ( MASTER_LOG , "Trying to load library %s" , filename );
if ( IsLoaded ())
{
LOG ( MASTER_LOG , "Trying to load already loaded library %s" , filename );
return 2 ;
}
#ifdef _WIN32
library = LoadLibrary ( filename );
#else
library = dlopen ( filename , RTLD_NOW | RTLD_LOCAL );
#endif
2008-12-17 15:34:27 +00:00
2008-12-25 15:56:36 +00:00
if ( ! library )
{
2008-12-17 15:34:27 +00:00
LOG ( MASTER_LOG , "Error loading DLL %s: %s" , filename , GetLastErrorAsString (). c_str ());
2008-12-25 15:56:36 +00:00
if ( File :: Exists ( filename ))
{
PanicAlert ( "Error loading DLL %s: %s \n\n Are you missing SDL.DLL or another file that this plugin may depend on?" , filename , GetLastErrorAsString (). c_str ());
}
else
{
PanicAlert ( "Error loading DLL %s: %s \n " , filename , GetLastErrorAsString (). c_str ());
}
2008-12-17 15:34:27 +00:00
return 0 ;
}
2008-12-08 05:30:24 +00:00
library_file = filename ;
return 1 ;
}
2008-12-17 15:34:27 +00:00
int DynamicLibrary :: Unload ()
2008-12-08 05:30:24 +00:00
{
2008-12-17 15:34:27 +00:00
int retval ;
if ( ! IsLoaded ()) {
PanicAlert ( "Error unloading DLL %s: not loaded" , library_file . c_str ());
return 0 ;
}
2008-12-08 05:30:24 +00:00
#ifdef _WIN32
2008-12-17 18:20:41 +00:00
retval = FreeLibrary ( library );
2008-12-08 05:30:24 +00:00
#else
2008-12-17 17:49:38 +00:00
retval = dlclose ( library ) ? 0 : 1 ;
2008-12-08 05:30:24 +00:00
#endif
2008-12-17 15:34:27 +00:00
if ( ! retval ) {
PanicAlert ( "Error unloading DLL %s: %s" , library_file . c_str (),
GetLastErrorAsString (). c_str ());
}
library = 0 ;
return retval ;
2008-12-08 05:30:24 +00:00
}
void * DynamicLibrary :: Get ( const char * funcname ) const
{
void * retval ;
if ( ! library )
{
2008-12-25 15:56:36 +00:00
PanicAlert ( "Can't find function %s - Library not loaded." );
return NULL ;
2008-12-08 05:30:24 +00:00
}
2008-12-17 15:34:27 +00:00
#ifdef _WIN32
2008-12-08 05:30:24 +00:00
retval = GetProcAddress ( library , funcname );
#else
retval = dlsym ( library , funcname );
#endif
2008-12-17 15:34:27 +00:00
if ( ! retval ) {
2008-12-25 15:56:36 +00:00
LOG ( MASTER_LOG , "Symbol %s missing in %s (error: %s) \n " , funcname , library_file . c_str (), GetLastErrorAsString (). c_str ());
PanicAlert ( "Symbol %s missing in %s (error: %s) \n " , funcname , library_file . c_str (), GetLastErrorAsString (). c_str ());
2008-12-17 15:34:27 +00:00
}
2008-12-08 05:30:24 +00:00
return retval ;
}