1
This commit is contained in:
148
tier0/dynfunction.cpp
Normal file
148
tier0/dynfunction.cpp
Normal file
@ -0,0 +1,148 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Shared library loading and symbol lookup.
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "pch_tier0.h"
|
||||
#include "tier0/dynfunction.h"
|
||||
|
||||
#if defined(WIN32)
|
||||
typedef HMODULE LibraryHandle;
|
||||
#define LoadLibraryHandle(libname) LoadLibrary(libname)
|
||||
#define CloseLibraryHandle(handle) FreeLibrary(handle)
|
||||
#define LookupInLibraryHandle(handle, fn) GetProcAddress(handle, fn)
|
||||
#elif defined(POSIX)
|
||||
#include <dlfcn.h>
|
||||
typedef void *LibraryHandle;
|
||||
#define LoadLibraryHandle(libname) dlopen(libname, RTLD_NOW)
|
||||
#define CloseLibraryHandle(handle) dlclose(handle)
|
||||
#define LookupInLibraryHandle(handle, fn) dlsym(handle, fn)
|
||||
#else
|
||||
#error Please define your platform.
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
static inline void dbgdynfn(const char *fmt, ...) {}
|
||||
#else
|
||||
#define dbgdynfn printf
|
||||
#endif
|
||||
|
||||
// NOTE: This has to be the last file included!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
class CSharedLibraryCache
|
||||
{
|
||||
public:
|
||||
static CSharedLibraryCache &GetCache()
|
||||
{
|
||||
static CSharedLibraryCache Singleton;
|
||||
return Singleton;
|
||||
}
|
||||
|
||||
struct CSharedLibraryItem
|
||||
{
|
||||
CSharedLibraryItem(LibraryHandle handle, const char *name)
|
||||
{
|
||||
m_handle = handle;
|
||||
m_name = new char[strlen(name) + 1];
|
||||
m_next = NULL;
|
||||
strcpy(m_name, name);
|
||||
}
|
||||
|
||||
~CSharedLibraryItem()
|
||||
{
|
||||
dbgdynfn("CDynamicFunction: Closing library '%s' (%p)\n", m_name, (void *) m_handle);
|
||||
CloseLibraryHandle(m_handle);
|
||||
delete[] m_name;
|
||||
delete m_next;
|
||||
}
|
||||
|
||||
char *m_name;
|
||||
CSharedLibraryItem *m_next;
|
||||
LibraryHandle m_handle;
|
||||
};
|
||||
|
||||
CSharedLibraryCache() : m_pList(NULL) {}
|
||||
~CSharedLibraryCache() { CloseAllLibraries(); }
|
||||
|
||||
LibraryHandle GetHandle(const char *name)
|
||||
{
|
||||
CSharedLibraryItem *item = GetCacheItem(name);
|
||||
if (item == NULL)
|
||||
{
|
||||
LibraryHandle lib = LoadLibraryHandle(name);
|
||||
dbgdynfn("CDynamicFunction: Loading library '%s' (%p)\n", name, (void *) lib);
|
||||
if (lib == NULL)
|
||||
return NULL;
|
||||
|
||||
item = new CSharedLibraryItem(lib, name);
|
||||
item->m_next = m_pList;
|
||||
m_pList = item;
|
||||
}
|
||||
return item->m_handle;
|
||||
}
|
||||
|
||||
void CloseLibrary(const char *name)
|
||||
{
|
||||
CSharedLibraryItem *item = GetCacheItem(name);
|
||||
if (item)
|
||||
{
|
||||
assert(item == m_pList);
|
||||
m_pList = item->m_next;
|
||||
item->m_next = NULL;
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
|
||||
void CloseAllLibraries()
|
||||
{
|
||||
delete m_pList;
|
||||
}
|
||||
|
||||
private:
|
||||
CSharedLibraryItem *GetCacheItem(const char *name)
|
||||
{
|
||||
CSharedLibraryItem *prev = NULL;
|
||||
CSharedLibraryItem *item = m_pList;
|
||||
while (item)
|
||||
{
|
||||
if (strcmp(item->m_name, name) == 0)
|
||||
{
|
||||
// move this item to the front of the list, since there will
|
||||
// probably be a big pile of these lookups in a row
|
||||
// and then none ever again.
|
||||
if (prev != NULL)
|
||||
{
|
||||
prev->m_next = item->m_next;
|
||||
item->m_next = m_pList;
|
||||
m_pList = item;
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
prev = item;
|
||||
item = item->m_next;
|
||||
}
|
||||
return NULL; // not found.
|
||||
}
|
||||
|
||||
CSharedLibraryItem *m_pList;
|
||||
};
|
||||
|
||||
void *VoidFnPtrLookup_Tier0(const char *libname, const char *fn, void *fallback)
|
||||
{
|
||||
LibraryHandle lib = CSharedLibraryCache::GetCache().GetHandle(libname);
|
||||
void *retval = NULL;
|
||||
if (lib != NULL)
|
||||
{
|
||||
retval = LookupInLibraryHandle(lib, fn);
|
||||
dbgdynfn("CDynamicFunction: Lookup of '%s' in '%s': %p\n", fn, libname, retval);
|
||||
}
|
||||
|
||||
if (retval == NULL)
|
||||
retval = fallback;
|
||||
return retval;
|
||||
}
|
||||
|
Reference in New Issue
Block a user