corelib/src/DynLib.cc
Emmanuel BENOîT 30d8d3057e Windows "compatibility"
* Makefile changes allowing for cross-compilation
* SRDData: had to rename an enum member from ERROR to ERR because
apparently creating a macro called ERROR is a thing in the windows
headers
* DynLib: ported
* Strings: fixes in toOSString, untested for now
* Fixes in some tests
* TODO list update
2018-06-17 12:39:02 +02:00

206 lines
4.5 KiB
C++

/******************************************************************************/
/* DYNAMIC LIBRARIES **********************************************************/
/******************************************************************************/
#include <ebcl/DynLib.hh>
#include <ebcl/Threading.hh>
using namespace ebcl;
#ifdef _WIN32
/*= T_DynLibWindows ==========================================================*/
namespace {
struct T_DynLibWindows_
{
T_Buffer< char > path;
T_String error;
HMODULE lib;
explicit T_DynLibWindows_( T_String const& path ) noexcept;
explicit T_DynLibWindows_( char const* const path ) noexcept;
~T_DynLibWindows_( ) noexcept;
bool load( ) noexcept;
void unload( ) noexcept;
bool isLoaded( ) const noexcept;
void* getSymbol( char const* const symbol ) noexcept;
};
} // namespace
/*----------------------------------------------------------------------------*/
inline T_DynLibWindows_::T_DynLibWindows_(
T_String const& path ) noexcept
: path( path.toOSString( ) ) , lib( nullptr )
{ }
inline T_DynLibWindows_::T_DynLibWindows_(
char const* const path ) noexcept
: path( path , strlen( path ) ) , lib( nullptr )
{ }
inline T_DynLibWindows_::~T_DynLibWindows_( ) noexcept
{
unload( );
}
/*----------------------------------------------------------------------------*/
inline bool T_DynLibWindows_::load( ) noexcept
{
lib = LoadLibraryW( (wchar_t const*) path.data( ) );
return lib != nullptr;
}
inline void T_DynLibWindows_::unload( ) noexcept
{
if ( lib != nullptr ) {
FreeLibrary( lib );
lib = nullptr;
}
}
inline bool T_DynLibWindows_::isLoaded( ) const noexcept
{
return lib != nullptr;
}
/*----------------------------------------------------------------------------*/
inline void* T_DynLibWindows_::getSymbol(
char const* const symbol ) noexcept
{
return (void*) GetProcAddress( lib , symbol );
}
using T_DynLibImpl_ = T_DynLibWindows_;
#else // ifdef _WIN32
/*= T_DynLibLinux_ ===========================================================*/
#include <dlfcn.h>
#include <atomic>
namespace {
struct T_DynLibLinux_
{
T_Buffer< char > path;
T_String error;
void* lib;
explicit T_DynLibLinux_( T_String const& path ) noexcept;
explicit T_DynLibLinux_( char const* const path ) noexcept;
~T_DynLibLinux_( ) noexcept;
bool load( ) noexcept;
void unload( ) noexcept;
bool isLoaded( ) const noexcept;
void* getSymbol( char const* const symbol ) noexcept;
};
} // namespace
/*----------------------------------------------------------------------------*/
inline T_DynLibLinux_::T_DynLibLinux_(
T_String const& path ) noexcept
: path( path.toOSString( ) ) , lib( nullptr )
{ }
inline T_DynLibLinux_::T_DynLibLinux_(
char const* const path ) noexcept
: path( path , strlen( path ) ) , lib( nullptr )
{ }
inline T_DynLibLinux_::~T_DynLibLinux_( ) noexcept
{
unload( );
}
/*----------------------------------------------------------------------------*/
inline bool T_DynLibLinux_::load( ) noexcept
{
if ( lib != nullptr ) {
return true;
}
lib = dlopen( &path[ 0 ] , RTLD_LOCAL | RTLD_NOW );
error = lib ? T_String{} : T_String{ dlerror( ) };
return lib != nullptr;
}
inline void T_DynLibLinux_::unload( ) noexcept
{
if ( lib != nullptr ) {
dlclose( lib );
lib = nullptr;
}
}
inline bool T_DynLibLinux_::isLoaded( ) const noexcept
{
return lib != nullptr;
}
/*----------------------------------------------------------------------------*/
inline void* T_DynLibLinux_::getSymbol(
char const* const symbol ) noexcept
{
assert( lib != nullptr );
void* const ptr( dlsym( lib , symbol ) );
error = ( ptr == nullptr ) ? T_String{ dlerror( ) } : T_String{};
return ptr;
}
using T_DynLibImpl_ = T_DynLibLinux_;
#endif // ifdef _WIN32
/*= T_DynLib =================================================================*/
T_DynLib::T_DynLib(
T_String const& name )
: A_PrivateImplementation( new T_DynLibImpl_( name ) )
{ }
T_DynLib::T_DynLib(
char const* const name )
: A_PrivateImplementation( new T_DynLibImpl_( name ) )
{ }
/*----------------------------------------------------------------------------*/
bool T_DynLib::load( )
{
return p< T_DynLibImpl_ >( ).load( );
}
void T_DynLib::unload( )
{
p< T_DynLibImpl_ >( ).unload( );
}
bool T_DynLib::isLoaded( ) const noexcept
{
return p< T_DynLibImpl_ >( ).isLoaded( );
}
T_String T_DynLib::lastError( ) const noexcept
{
return p< T_DynLibImpl_ >( ).error;
}
/*----------------------------------------------------------------------------*/
void* T_DynLib::getRawSymbol(
char const* const name ) const noexcept
{
return p< T_DynLibImpl_ >( ).getSymbol( name );
}