ReGameDLL_CS/regamedll/public/interface.h

124 lines
4.9 KiB
C
Raw Normal View History

2015-06-30 12:46:07 +03:00
// This header defines the interface convention used in the valve engine.
// To make an interface and expose it:
// 1. Derive from IBaseInterface.
// 2. The interface must be ALL pure virtuals, and have no data members.
// 3. Define a name for it.
// 4. In its implementation file, use EXPOSE_INTERFACE or EXPOSE_SINGLE_INTERFACE.
// Versioning
// There are two versioning cases that are handled by this:
2017-10-12 17:50:56 +03:00
// 1. You add functions to the end of an interface, so it is binary compatible with the previous interface. In this case,
2015-06-30 12:46:07 +03:00
// you need two EXPOSE_INTERFACEs: one to expose your class as the old interface and one to expose it as the new interface.
2017-10-12 17:50:56 +03:00
// 2. You update an interface so it's not compatible anymore (but you still want to be able to expose the old interface
// for legacy code). In this case, you need to make a new version name for your new interface, and make a wrapper interface and
2015-06-30 12:46:07 +03:00
// expose it for the old interface.
2017-10-12 17:50:56 +03:00
#pragma once
2015-06-30 12:46:07 +03:00
2017-10-12 17:50:56 +03:00
#ifndef _WIN32
2015-06-30 12:46:07 +03:00
2017-10-12 17:50:56 +03:00
#include <dlfcn.h> // dlopen, dlclose, et al
2015-06-30 12:46:07 +03:00
#include <unistd.h>
#define HMODULE void *
#define GetProcAddress dlsym
#define _snprintf snprintf
2017-10-12 17:50:56 +03:00
#endif // _WIN32
2015-06-30 12:46:07 +03:00
void *Sys_GetProcAddress(const char *pModuleName, const char *pName);
void *Sys_GetProcAddress(void *pModuleHandle, const char *pName);
// All interfaces derive from this.
class IBaseInterface
{
public:
2017-10-12 17:50:56 +03:00
virtual ~IBaseInterface() {}
2015-06-30 12:46:07 +03:00
};
2017-10-12 17:50:56 +03:00
#define CREATEINTERFACE_PROCNAME "CreateInterface"
2015-06-30 12:46:07 +03:00
2017-10-12 17:50:56 +03:00
typedef IBaseInterface *(*CreateInterfaceFn)(const char *pName, int *pReturnCode);
typedef IBaseInterface *(*InstantiateInterfaceFn)();
2015-06-30 12:46:07 +03:00
// Used internally to register classes.
class InterfaceReg
{
public:
InterfaceReg(InstantiateInterfaceFn fn, const char *pName);
public:
2017-10-12 17:50:56 +03:00
InstantiateInterfaceFn m_CreateFn;
const char *m_pName;
2015-06-30 12:46:07 +03:00
2017-10-12 17:50:56 +03:00
InterfaceReg *m_pNext; // For the global list.
static InterfaceReg *s_pInterfaceRegs;
2015-06-30 12:46:07 +03:00
};
// Use this to expose an interface that can have multiple instances.
// e.g.:
2017-10-12 17:50:56 +03:00
// EXPOSE_INTERFACE(CInterfaceImp, IInterface, "MyInterface001")
2015-06-30 12:46:07 +03:00
// This will expose a class called CInterfaceImp that implements IInterface (a pure class)
2017-10-12 17:50:56 +03:00
// clients can receive a pointer to this class by calling CreateInterface("MyInterface001")
2015-06-30 12:46:07 +03:00
//
// In practice, the shared header file defines the interface (IInterface) and version name ("MyInterface001")
// so that each component can use these names/vtables to communicate
//
// A single class can support multiple interfaces through multiple inheritance
//
// Use this if you want to write the factory function.
2017-10-12 17:50:56 +03:00
#define EXPOSE_INTERFACE_FN(functionName, interfaceName, versionName)\
2015-06-30 12:46:07 +03:00
static InterfaceReg __g_Create##className##_reg(functionName, versionName);
2017-10-12 17:50:56 +03:00
#define EXPOSE_INTERFACE(className, interfaceName, versionName)\
static IBaseInterface *__Create##className##_interface() {return (interfaceName *)new className;}\
static InterfaceReg __g_Create##className##_reg(__Create##className##_interface, versionName);
2015-06-30 12:46:07 +03:00
// Use this to expose a singleton interface with a global variable you've created.
2017-10-12 17:50:56 +03:00
#define EXPOSE_SINGLE_INTERFACE_GLOBALVAR(className, interfaceName, versionName, globalVarName)\
static IBaseInterface *__Create##className##interfaceName##_interface() {return (IBaseInterface *)&globalVarName;}\
2015-06-30 12:46:07 +03:00
static InterfaceReg __g_Create##className##interfaceName##_reg(__Create##className##interfaceName##_interface, versionName);
// Use this to expose a singleton interface. This creates the global variable for you automatically.
2017-10-12 17:50:56 +03:00
#define EXPOSE_SINGLE_INTERFACE(className, interfaceName, versionName)\
2015-06-30 12:46:07 +03:00
static className __g_##className##_singleton;\
EXPOSE_SINGLE_INTERFACE_GLOBALVAR(className, interfaceName, versionName, __g_##className##_singleton)
#ifdef _WIN32
2017-10-12 17:50:56 +03:00
#define EXPORT_FUNCTION __declspec(dllexport) EXT_FUNC
2015-06-30 12:46:07 +03:00
#else
2017-10-12 17:50:56 +03:00
#define EXPORT_FUNCTION __attribute__((visibility("default"))) EXT_FUNC
#endif // _WIN32
2015-06-30 12:46:07 +03:00
// This function is automatically exported and allows you to access any interfaces exposed with the above macros.
// if pReturnCode is set, it will return one of the following values
// extend this for other error conditions/code
2017-10-12 17:50:56 +03:00
enum
2015-06-30 12:46:07 +03:00
{
IFACE_OK = 0,
IFACE_FAILED
};
extern "C"
{
2017-10-12 17:50:56 +03:00
EXPORT_FUNCTION IBaseInterface *CreateInterface(const char *pName, int *pReturnCode);
2015-06-30 12:46:07 +03:00
};
2017-10-12 17:50:56 +03:00
extern CreateInterfaceFn Sys_GetFactoryThis();
2015-06-30 12:46:07 +03:00
// UNDONE: This is obsolete, use the module load/unload/get instead!!!
2017-10-12 17:50:56 +03:00
extern CreateInterfaceFn Sys_GetFactory(const char *pModuleName);
2015-06-30 12:46:07 +03:00
// load/unload components
class CSysModule;
// Load & Unload should be called in exactly one place for each module
// The factory for that module should be passed on to dependent components for
// proper versioning.
2017-10-12 17:50:56 +03:00
extern CSysModule *Sys_LoadModule(const char *pModuleName);
extern void Sys_UnloadModule(CSysModule *pModule);
extern CreateInterfaceFn Sys_GetFactory(CSysModule *pModule);
extern void *InitializeInterface(char const *interfaceName, CreateInterfaceFn *factoryList, int numFactories);