2
0
mirror of https://github.com/rehlds/metamod-r.git synced 2024-12-31 00:55:47 +03:00
metamod-r/metamod/include/public/interface.cpp

237 lines
6.8 KiB
C++
Raw Normal View History

2017-07-31 18:37:50 +03:00
/*
*
* 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; either version 2 of the License, or (at
* your option) any later version.
*
* 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
2016-07-26 03:22:47 +03:00
2017-07-31 18:37:50 +03:00
#include "interface.h"
2016-07-26 03:22:47 +03:00
2017-07-31 18:37:50 +03:00
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
#endif // _WIN32
2016-07-26 03:22:47 +03:00
2017-07-31 18:37:50 +03:00
// InterfaceReg
InterfaceReg *InterfaceReg::s_pInterfaceRegs = nullptr;
2016-07-26 03:22:47 +03:00
2017-07-31 18:37:50 +03:00
InterfaceReg::InterfaceReg(InstantiateInterfaceFn fn, const char *pName) : m_pName(pName)
2016-07-26 03:22:47 +03:00
{
m_CreateFn = fn;
m_pNext = s_pInterfaceRegs;
s_pInterfaceRegs = this;
}
2017-07-31 18:37:50 +03:00
// This is the primary exported function by a dll, referenced by name via dynamic binding
// that exposes an opqaue function pointer to the interface.
//
// We have the Internal variant so Sys_GetFactoryThis() returns the correct internal
// symbol under GCC/Linux/Mac as CreateInterface is DLL_EXPORT so its global so the loaders
// on those OS's pick exactly 1 of the CreateInterface symbols to be the one that is process wide and
// all Sys_GetFactoryThis() calls find that one, which doesn't work. Using the internal walkthrough here
// makes sure Sys_GetFactoryThis() has the dll specific symbol and GetProcAddress() returns the module specific
// function for CreateInterface again getting the dll specific symbol we need.
EXPORT_FUNCTION IBaseInterface *CreateInterface(const char *pName, int *pReturnCode)
2016-07-26 03:22:47 +03:00
{
InterfaceReg *pCur;
2017-07-31 18:37:50 +03:00
for (pCur = InterfaceReg::s_pInterfaceRegs; pCur; pCur = pCur->m_pNext)
2016-07-26 03:22:47 +03:00
{
2017-07-31 18:37:50 +03:00
if (strcmp(pCur->m_pName, pName) == 0)
2016-07-26 03:22:47 +03:00
{
2017-07-31 18:37:50 +03:00
if (pReturnCode)
2016-07-26 03:22:47 +03:00
{
*pReturnCode = IFACE_OK;
}
2017-07-31 18:37:50 +03:00
2016-07-26 03:22:47 +03:00
return pCur->m_CreateFn();
}
}
2017-07-31 18:37:50 +03:00
if (pReturnCode)
2016-07-26 03:22:47 +03:00
{
*pReturnCode = IFACE_FAILED;
}
2017-07-31 18:37:50 +03:00
return nullptr;
2016-07-26 03:22:47 +03:00
}
2017-07-31 18:37:50 +03:00
#ifndef _WIN32
// Linux doesn't have this function so this emulates its functionality
void *GetModuleHandle(const char *name)
2016-07-26 03:22:47 +03:00
{
2017-07-31 18:37:50 +03:00
void *handle;
if (name == nullptr)
2016-07-26 03:22:47 +03:00
{
2017-07-31 18:37:50 +03:00
// hmm, how can this be handled under linux....
// is it even needed?
return nullptr;
2016-07-26 03:22:47 +03:00
}
2017-07-31 18:37:50 +03:00
if ((handle = dlopen(name, RTLD_NOW)) == nullptr)
2016-07-26 03:22:47 +03:00
{
2017-07-31 18:37:50 +03:00
//printf("Error:%s\n",dlerror());
// couldn't open this file
return nullptr;
2016-07-26 03:22:47 +03:00
}
2017-07-31 18:37:50 +03:00
// 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 // _WIN32
2016-07-26 03:22:47 +03:00
// Purpose: returns a pointer to a function, given a module
// Input : pModuleName - module name
// *pName - proc name
2017-07-31 18:37:50 +03:00
//static hlds_run wants to use this function
void *Sys_GetProcAddress(const char *pModuleName, const char *pName)
2016-07-26 03:22:47 +03:00
{
2017-07-31 18:37:50 +03:00
return GetProcAddress(GetModuleHandle(pModuleName), pName);
2016-07-26 03:22:47 +03:00
}
// Purpose: returns a pointer to a function, given a module
// Input : pModuleName - module name
// *pName - proc name
2017-07-31 18:37:50 +03:00
// hlds_run wants to use this function
void *Sys_GetProcAddress(void *pModuleHandle, const char *pName)
2016-07-26 03:22:47 +03:00
{
2017-07-31 18:37:50 +03:00
return GetProcAddress((HMODULE)pModuleHandle, pName);
2016-07-26 03:22:47 +03:00
}
// 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)
2017-07-31 18:37:50 +03:00
CSysModule *Sys_LoadModule(const char *pModuleName)
2016-07-26 03:22:47 +03:00
{
2017-07-31 18:37:50 +03:00
#ifdef _WIN32
HMODULE hDLL = LoadLibrary(pModuleName);
2016-07-26 03:22:47 +03:00
#else
2017-07-31 18:37:50 +03:00
HMODULE hDLL = nullptr;
2016-07-26 03:22:47 +03:00
char szAbsoluteModuleName[1024];
2017-07-31 18:37:50 +03:00
if (pModuleName[0] != '/')
2016-07-26 03:22:47 +03:00
{
char szCwd[1024];
2017-07-31 18:37:50 +03:00
getcwd(szCwd, sizeof(szCwd));
if (szCwd[strlen(szCwd) - 1] == '/')
szCwd[strlen(szCwd) - 1] = '\0';
2016-07-26 03:22:47 +03:00
2017-07-31 18:37:50 +03:00
_snprintf(szAbsoluteModuleName, sizeof(szAbsoluteModuleName), "%s/%s", szCwd, pModuleName);
hDLL = dlopen(szAbsoluteModuleName, RTLD_NOW);
2016-07-26 03:22:47 +03:00
}
else
{
2017-07-31 18:37:50 +03:00
_snprintf(szAbsoluteModuleName, sizeof(szAbsoluteModuleName), "%s", pModuleName);
hDLL = dlopen(pModuleName, RTLD_NOW);
2016-07-26 03:22:47 +03:00
}
2017-07-31 18:37:50 +03:00
#endif // _WIN32
2016-07-26 03:22:47 +03:00
2017-07-31 18:37:50 +03:00
if (!hDLL)
2016-07-26 03:22:47 +03:00
{
char str[512];
2017-07-31 18:37:50 +03:00
#if defined(_WIN32)
_snprintf(str, sizeof(str), "%s.dll", pModuleName);
hDLL = LoadLibrary(str);
2016-07-26 03:22:47 +03:00
#elif defined(OSX)
2017-07-31 18:37:50 +03:00
printf("Error: %s\n", dlerror());
_snprintf(str, sizeof(str), "%s.dylib", szAbsoluteModuleName);
hDLL = dlopen(str, RTLD_NOW);
2016-07-26 03:22:47 +03:00
#else
2017-07-31 18:37:50 +03:00
printf("Error: %s\n", dlerror());
_snprintf(str, sizeof(str), "%s.so", szAbsoluteModuleName);
2016-07-26 03:22:47 +03:00
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)
2017-07-31 18:37:50 +03:00
void Sys_UnloadModule(CSysModule *pModule)
2016-07-26 03:22:47 +03:00
{
2017-07-31 18:37:50 +03:00
if (!pModule)
2016-07-26 03:22:47 +03:00
return;
HMODULE hDLL = reinterpret_cast<HMODULE>(pModule);
2017-07-31 18:37:50 +03:00
#ifdef _WIN32
FreeLibrary(hDLL);
#else
dlclose(hDLL);
#endif // _WIN32
2016-07-26 03:22:47 +03:00
}
// Purpose: returns a pointer to a function, given a module
2017-07-31 18:37:50 +03:00
// Input : module - windows HMODULE from Sys_LoadModule()
2016-07-26 03:22:47 +03:00
// *pName - proc name
// Output : factory for this module
2017-07-31 18:37:50 +03:00
CreateInterfaceFn Sys_GetFactory(CSysModule *pModule)
2016-07-26 03:22:47 +03:00
{
2017-07-31 18:37:50 +03:00
if (!pModule)
return nullptr;
2016-07-26 03:22:47 +03:00
2017-07-31 18:37:50 +03:00
return reinterpret_cast<CreateInterfaceFn>(Sys_GetProcAddress(pModule, CREATEINTERFACE_PROCNAME));
2016-07-26 03:22:47 +03:00
}
// Purpose: returns the instance of this module
2017-07-31 18:37:50 +03:00
// Output : CreateInterfaceFn
CreateInterfaceFn Sys_GetFactoryThis()
2016-07-26 03:22:47 +03:00
{
return CreateInterface;
}
// Purpose: returns the instance of the named module
// Input : *pModuleName - name of the module
2017-07-31 18:37:50 +03:00
// Output : CreateInterfaceFn - instance of that module
CreateInterfaceFn Sys_GetFactory(const char *pModuleName)
2016-07-26 03:22:47 +03:00
{
2017-07-31 18:37:50 +03:00
return reinterpret_cast<CreateInterfaceFn>(Sys_GetProcAddress(pModuleName, CREATEINTERFACE_PROCNAME));
}
// Purpose: finds a particular interface in the factory set
void *InitializeInterface(char const *interfaceName, CreateInterfaceFn *factoryList, int numFactories)
{
void *retval;
for (int i = 0; i < numFactories; i++)
{
CreateInterfaceFn factory = factoryList[ i ];
if (!factory)
continue;
retval = factory(interfaceName, nullptr);
if (retval)
return retval;
}
// No provider for requested interface!!!
// assert(!"No provider for requested interface!!!");
return nullptr;
2016-07-26 03:22:47 +03:00
}