mirror of
https://github.com/rehlds/resemiclip.git
synced 2024-12-26 06:35:52 +03:00
8cae39a981
Prefer Sys_GetModuleHandle over Sys_LoadModule to avoid unnecessary reference count increase
272 lines
7.6 KiB
C++
272 lines
7.6 KiB
C++
#include "precompiled.h"
|
|
#include "interface.h"
|
|
|
|
#if !defined ( _WIN32 )
|
|
// Linux doesn't have this function so this emulates its functionality
|
|
//
|
|
//
|
|
void *GetModuleHandle(const char *name)
|
|
{
|
|
void *handle;
|
|
|
|
if (name == NULL)
|
|
{
|
|
// hmm, how can this be handled under linux....
|
|
// is it even needed?
|
|
return NULL;
|
|
}
|
|
|
|
if ((handle=dlopen(name, RTLD_NOW)) == NULL)
|
|
{
|
|
//printf("Error:%s\n",dlerror());
|
|
// couldn't open this file
|
|
return NULL;
|
|
}
|
|
|
|
// read "man dlopen" for details
|
|
// in short dlopen() inc a ref count
|
|
// so dec the ref count by performing the close
|
|
dlclose(handle);
|
|
return handle;
|
|
}
|
|
#endif
|
|
|
|
// ------------------------------------------------------------------------------------ //
|
|
// InterfaceReg.
|
|
// ------------------------------------------------------------------------------------ //
|
|
InterfaceReg *InterfaceReg::s_pInterfaceRegs = NULL;
|
|
|
|
|
|
InterfaceReg::InterfaceReg( InstantiateInterfaceFn fn, const char *pName ) : m_pName(pName)
|
|
{
|
|
m_CreateFn = fn;
|
|
m_pNext = s_pInterfaceRegs;
|
|
s_pInterfaceRegs = this;
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------ //
|
|
// CreateInterface.
|
|
// ------------------------------------------------------------------------------------ //
|
|
EXPORT_FUNCTION IBaseInterface *CreateInterface( const char *pName, int *pReturnCode )
|
|
{
|
|
InterfaceReg *pCur;
|
|
|
|
for(pCur=InterfaceReg::s_pInterfaceRegs; pCur; pCur=pCur->m_pNext)
|
|
{
|
|
if(strcmp(pCur->m_pName, pName) == 0)
|
|
{
|
|
if ( pReturnCode )
|
|
{
|
|
*pReturnCode = IFACE_OK;
|
|
}
|
|
return pCur->m_CreateFn();
|
|
}
|
|
}
|
|
|
|
if ( pReturnCode )
|
|
{
|
|
*pReturnCode = IFACE_FAILED;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
#ifdef LINUX
|
|
static IBaseInterface *CreateInterfaceLocal( const char *pName, int *pReturnCode )
|
|
{
|
|
InterfaceReg *pCur;
|
|
|
|
for(pCur=InterfaceReg::s_pInterfaceRegs; pCur; pCur=pCur->m_pNext)
|
|
{
|
|
if(strcmp(pCur->m_pName, pName) == 0)
|
|
{
|
|
if ( pReturnCode )
|
|
{
|
|
*pReturnCode = IFACE_OK;
|
|
}
|
|
return pCur->m_CreateFn();
|
|
}
|
|
}
|
|
|
|
if ( pReturnCode )
|
|
{
|
|
*pReturnCode = IFACE_FAILED;
|
|
}
|
|
return NULL;
|
|
}
|
|
#endif
|
|
|
|
#ifdef _WIN32
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#include "windows.h"
|
|
#endif
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: returns a pointer to a function, given a module
|
|
// Input : pModuleName - module name
|
|
// *pName - proc name
|
|
//-----------------------------------------------------------------------------
|
|
//static hlds_run wants to use this function
|
|
void *Sys_GetProcAddress( const char *pModuleName, const char *pName )
|
|
{
|
|
return GetProcAddress( GetModuleHandle(pModuleName), pName );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: returns a pointer to a function, given a module
|
|
// Input : pModuleName - module name
|
|
// *pName - proc name
|
|
//-----------------------------------------------------------------------------
|
|
// hlds_run wants to use this function
|
|
void *Sys_GetProcAddress( void *pModuleHandle, const char *pName )
|
|
{
|
|
#if defined ( _WIN32 )
|
|
return GetProcAddress( (HINSTANCE)pModuleHandle, pName );
|
|
#else
|
|
return GetProcAddress( pModuleHandle, pName );
|
|
#endif
|
|
}
|
|
|
|
// Purpose: Returns a module handle by its name.
|
|
// Input : pModuleName - module name
|
|
// Output : the module handle or NULL in case of an error
|
|
CSysModule *Sys_GetModuleHandle(const char *pModuleName)
|
|
{
|
|
return reinterpret_cast<CSysModule *>(GetModuleHandle(pModuleName));
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Loads a DLL/component from disk and returns a handle to it
|
|
// Input : *pModuleName - filename of the component
|
|
// Output : opaque handle to the module (hides system dependency)
|
|
//-----------------------------------------------------------------------------
|
|
CSysModule *Sys_LoadModule( const char *pModuleName )
|
|
{
|
|
#if defined ( _WIN32 )
|
|
HMODULE hDLL = LoadLibrary( pModuleName );
|
|
#else
|
|
HMODULE hDLL = NULL;
|
|
char szAbsoluteModuleName[1024];
|
|
szAbsoluteModuleName[0] = 0;
|
|
if ( pModuleName[0] != '/' )
|
|
{
|
|
char szCwd[1024];
|
|
char szAbsoluteModuleName[1024];
|
|
|
|
getcwd( szCwd, sizeof( szCwd ) );
|
|
if ( szCwd[ strlen( szCwd ) - 1 ] == '/' )
|
|
szCwd[ strlen( szCwd ) - 1 ] = 0;
|
|
|
|
_snprintf( szAbsoluteModuleName, sizeof(szAbsoluteModuleName), "%s/%s", szCwd, pModuleName );
|
|
|
|
hDLL = dlopen( szAbsoluteModuleName, RTLD_NOW );
|
|
}
|
|
else
|
|
{
|
|
_snprintf( szAbsoluteModuleName, sizeof(szAbsoluteModuleName), "%s", pModuleName );
|
|
hDLL = dlopen( pModuleName, RTLD_NOW );
|
|
}
|
|
#endif
|
|
|
|
if( !hDLL )
|
|
{
|
|
char str[512];
|
|
#if defined ( _WIN32 )
|
|
_snprintf( str, sizeof(str), "%s.dll", pModuleName );
|
|
hDLL = LoadLibrary( str );
|
|
#elif defined(OSX)
|
|
printf("Error:%s\n",dlerror());
|
|
_snprintf( str, sizeof(str), "%s.dylib", szAbsoluteModuleName );
|
|
hDLL = dlopen(str, RTLD_NOW);
|
|
#else
|
|
printf("Error:%s\n",dlerror());
|
|
_snprintf( str, sizeof(str), "%s.so", szAbsoluteModuleName );
|
|
hDLL = dlopen(str, RTLD_NOW);
|
|
#endif
|
|
}
|
|
|
|
return reinterpret_cast<CSysModule *>(hDLL);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Unloads a DLL/component from
|
|
// Input : *pModuleName - filename of the component
|
|
// Output : opaque handle to the module (hides system dependency)
|
|
//-----------------------------------------------------------------------------
|
|
void Sys_UnloadModule( CSysModule *pModule )
|
|
{
|
|
if ( !pModule )
|
|
return;
|
|
|
|
HMODULE hDLL = reinterpret_cast<HMODULE>(pModule);
|
|
#if defined ( _WIN32 )
|
|
FreeLibrary( hDLL );
|
|
#else
|
|
dlclose((void *)hDLL);
|
|
#endif
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: returns a pointer to a function, given a module
|
|
// Input : module - windows HMODULE from Sys_LoadModule()
|
|
// *pName - proc name
|
|
// Output : factory for this module
|
|
//-----------------------------------------------------------------------------
|
|
CreateInterfaceFn Sys_GetFactory( CSysModule *pModule )
|
|
{
|
|
if ( !pModule )
|
|
return NULL;
|
|
|
|
HMODULE hDLL = reinterpret_cast<HMODULE>(pModule);
|
|
#if defined ( _WIN32 )
|
|
return reinterpret_cast<CreateInterfaceFn>(GetProcAddress( hDLL, CREATEINTERFACE_PROCNAME ));
|
|
#else
|
|
// Linux gives this error:
|
|
//../public/interface.cpp: In function `IBaseInterface *(*Sys_GetFactory
|
|
//(CSysModule *)) (const char *, int *)':
|
|
//../public/interface.cpp:154: ISO C++ forbids casting between
|
|
//pointer-to-function and pointer-to-object
|
|
//
|
|
// so lets get around it :)
|
|
return (CreateInterfaceFn)(GetProcAddress( hDLL, CREATEINTERFACE_PROCNAME ));
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: returns the instance of this module
|
|
// Output : interface_instance_t
|
|
//-----------------------------------------------------------------------------
|
|
CreateInterfaceFn Sys_GetFactoryThis( void )
|
|
{
|
|
#ifdef LINUX
|
|
return CreateInterfaceLocal;
|
|
#else
|
|
return CreateInterface;
|
|
#endif
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: returns the instance of the named module
|
|
// Input : *pModuleName - name of the module
|
|
// Output : interface_instance_t - instance of that module
|
|
//-----------------------------------------------------------------------------
|
|
CreateInterfaceFn Sys_GetFactory( const char *pModuleName )
|
|
{
|
|
#if defined ( _WIN32 )
|
|
return static_cast<CreateInterfaceFn>( Sys_GetProcAddress( pModuleName, CREATEINTERFACE_PROCNAME ) );
|
|
#else
|
|
// Linux gives this error:
|
|
//../public/interface.cpp: In function `IBaseInterface *(*Sys_GetFactory
|
|
//(const char *)) (const char *, int *)':
|
|
//../public/interface.cpp:186: invalid static_cast from type `void *' to
|
|
//type `IBaseInterface *(*) (const char *, int *)'
|
|
//
|
|
// so lets use the old style cast.
|
|
return (CreateInterfaceFn)( Sys_GetProcAddress( pModuleName, CREATEINTERFACE_PROCNAME ) );
|
|
#endif
|
|
}
|