นี่ไม่ใช่ประเด็นร้อน แต่ฉันมีคลาสโรงงานที่อนุญาตให้ dll สร้างอินสแตนซ์และส่งคืนเป็น DLL มันคือสิ่งที่ฉันมองหา แต่หาไม่เจอ
เรียกว่าชอบ
IHTTP_Server *server = SN::SN_Factory<IHTTP_Server>::CreateObject();
IHTTP_Server *server2 =
SN::SN_Factory<IHTTP_Server>::CreateObject(IHTTP_Server_special_entry);
โดยที่ IHTTP_Server เป็นอินเทอร์เฟซเสมือนจริงสำหรับคลาสที่สร้างขึ้นใน DLL อื่นหรือแบบเดียวกัน
DEFINE_INTERFACE ใช้เพื่อให้ ID คลาสมีอินเทอร์เฟซ วางอินเทอร์เฟซภายใน
คลาสอินเทอร์เฟซดูเหมือนว่า
class IMyInterface
{
DEFINE_INTERFACE(IMyInterface);
public:
virtual ~IMyInterface() {};
virtual void MyMethod1() = 0;
...
};
ไฟล์ส่วนหัวเป็นแบบนี้
#if !defined(SN_FACTORY_H_INCLUDED)
#define SN_FACTORY_H_INCLUDED
#pragma once
ไลบรารีถูกระบุไว้ในข้อกำหนดมาโครนี้ หนึ่งบรรทัดต่อไลบรารี / ปฏิบัติการ มันจะดีมากถ้าเราสามารถเรียกใช้ปฏิบัติการอื่นได้
#define SN_APPLY_LIBRARIES(L, A) \
L(A, sn, "sn.dll") \
L(A, http_server_lib, "http_server_lib.dll") \
L(A, http_server, "")
จากนั้นสำหรับแต่ละ dll / exe คุณกำหนดมาโครและแสดงรายการการใช้งาน Def หมายความว่าเป็นการใช้งานเริ่มต้นสำหรับอินเทอร์เฟซ หากไม่ใช่ค่าเริ่มต้นคุณต้องตั้งชื่อสำหรับอินเทอร์เฟซที่ใช้ระบุ กล่าวคือพิเศษและชื่อจะเป็น IHTTP_Server_special_entry
#define SN_APPLY_ENTRYPOINTS_sn(M) \
M(IHTTP_Handler, SNI::SNI_HTTP_Handler, sn, def) \
M(IHTTP_Handler, SNI::SNI_HTTP_Handler, sn, special)
#define SN_APPLY_ENTRYPOINTS_http_server_lib(M) \
M(IHTTP_Server, HTTP::server::server, http_server_lib, def)
#define SN_APPLY_ENTRYPOINTS_http_server(M)
ด้วยการตั้งค่าไลบรารีทั้งหมดไฟล์ส่วนหัวจะใช้ข้อกำหนดมาโครเพื่อกำหนดสิ่งที่จำเป็น
#define APPLY_ENTRY(A, N, L) \
SN_APPLY_ENTRYPOINTS_##N(A)
#define DEFINE_INTERFACE(I) \
public: \
static const long Id = SN::I##_def_entry; \
private:
namespace SN
{
#define DEFINE_LIBRARY_ENUM(A, N, L) \
N##_library,
สิ่งนี้จะสร้าง enum สำหรับไลบรารี
enum LibraryValues
{
SN_APPLY_LIBRARIES(DEFINE_LIBRARY_ENUM, "")
LastLibrary
};
#define DEFINE_ENTRY_ENUM(I, C, L, D) \
I##_##D##_entry,
สิ่งนี้สร้าง enum สำหรับการใช้งานอินเทอร์เฟซ
enum EntryValues
{
SN_APPLY_LIBRARIES(APPLY_ENTRY, DEFINE_ENTRY_ENUM)
LastEntry
};
long CallEntryPoint(long id, long interfaceId);
สิ่งนี้กำหนดระดับโรงงาน ไม่มากไปที่นี่
template <class I>
class SN_Factory
{
public:
SN_Factory()
{
}
static I *CreateObject(long id = I::Id )
{
return (I *)CallEntryPoint(id, I::Id);
}
};
}
#endif
CPP คือ
#include "sn_factory.h"
#include <windows.h>
สร้างจุดเข้าภายนอก คุณสามารถตรวจสอบว่ามีอยู่โดยใช้ขึ้นอยู่กับ.exe
extern "C"
{
__declspec(dllexport) long entrypoint(long id)
{
#define CREATE_OBJECT(I, C, L, D) \
case SN::I##_##D##_entry: return (int) new C();
switch (id)
{
SN_APPLY_CURRENT_LIBRARY(APPLY_ENTRY, CREATE_OBJECT)
case -1:
default:
return 0;
}
}
}
มาโครตั้งค่าข้อมูลทั้งหมดที่จำเป็น
namespace SN
{
bool loaded = false;
char * libraryPathArray[SN::LastLibrary];
#define DEFINE_LIBRARY_PATH(A, N, L) \
libraryPathArray[N##_library] = L;
static void LoadLibraryPaths()
{
SN_APPLY_LIBRARIES(DEFINE_LIBRARY_PATH, "")
}
typedef long(*f_entrypoint)(long id);
f_entrypoint libraryFunctionArray[LastLibrary - 1];
void InitlibraryFunctionArray()
{
for (long j = 0; j < LastLibrary; j++)
{
libraryFunctionArray[j] = 0;
}
#define DEFAULT_LIBRARY_ENTRY(A, N, L) \
libraryFunctionArray[N##_library] = &entrypoint;
SN_APPLY_CURRENT_LIBRARY(DEFAULT_LIBRARY_ENTRY, "")
}
enum SN::LibraryValues libraryForEntryPointArray[SN::LastEntry];
#define DEFINE_ENTRY_POINT_LIBRARY(I, C, L, D) \
libraryForEntryPointArray[I##_##D##_entry] = L##_library;
void LoadLibraryForEntryPointArray()
{
SN_APPLY_LIBRARIES(APPLY_ENTRY, DEFINE_ENTRY_POINT_LIBRARY)
}
enum SN::EntryValues defaultEntryArray[SN::LastEntry];
#define DEFINE_ENTRY_DEFAULT(I, C, L, D) \
defaultEntryArray[I##_##D##_entry] = I##_def_entry;
void LoadDefaultEntries()
{
SN_APPLY_LIBRARIES(APPLY_ENTRY, DEFINE_ENTRY_DEFAULT)
}
void Initialize()
{
if (!loaded)
{
loaded = true;
LoadLibraryPaths();
InitlibraryFunctionArray();
LoadLibraryForEntryPointArray();
LoadDefaultEntries();
}
}
long CallEntryPoint(long id, long interfaceId)
{
Initialize();
enum SN::LibraryValues l = libraryForEntryPointArray[id];
f_entrypoint f = libraryFunctionArray[l];
if (!f)
{
HINSTANCE hGetProcIDDLL = LoadLibraryA(libraryPathArray[l]);
if (!hGetProcIDDLL) {
return NULL;
}
f = (f_entrypoint)GetProcAddress(hGetProcIDDLL, "entrypoint");
if (!f) {
return NULL;
}
libraryFunctionArray[l] = f;
}
return f(id);
}
}
แต่ละไลบรารีมี "cpp" นี้พร้อมกับต้นขั้ว cpp สำหรับแต่ละไลบรารี / ปฏิบัติการ เนื้อหาส่วนหัวที่คอมไพล์โดยเฉพาะ
#include "sn_pch.h"
ตั้งค่าไลบรารีนี้
#define SN_APPLY_CURRENT_LIBRARY(L, A) \
L(A, sn, "sn.dll")
รวมสำหรับ cpp หลัก ฉันเดาว่า cpp นี้อาจเป็น. h แต่มีหลายวิธีที่คุณสามารถทำได้ วิธีนี้ใช้ได้ผลสำหรับฉัน
#include "../inc/sn_factory.cpp"