এটি ঠিক একটি উত্তপ্ত বিষয় নয়, তবে আমার একটি কারখানার ক্লাস রয়েছে যা একটি ডেলকে একটি উদাহরণ তৈরি করতে এবং এটি একটি ডিএলএল হিসাবে ফেরত দেওয়ার অনুমতি দেয়। এটি আমি যা খুঁজতে এসেছি কিন্তু সঠিকভাবে খুঁজে পাইনি।
এটিকে বলা হয়,
IHTTP_Server *server = SN::SN_Factory<IHTTP_Server>::CreateObject();
IHTTP_Server *server2 =
SN::SN_Factory<IHTTP_Server>::CreateObject(IHTTP_Server_special_entry);
যেখানে IHTTP_Server হয় অন্য কোনও ডিএলএল বা একই জাতীয় কোনও শ্রেণীর জন্য তৈরি খাঁটি ভার্চুয়াল ইন্টারফেস।
DEFINE_INTERFACE ক্লাস আইডিকে একটি ইন্টারফেস দেওয়ার জন্য ব্যবহৃত হয়। ইন্টারফেসের ভিতরে রাখুন;
একটি ইন্টারফেস শ্রেণীর মত দেখাচ্ছে,
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, "")
তারপরে প্রতিটি ডিএল / এক্সের জন্য আপনি একটি ম্যাক্রো সংজ্ঞায়িত করেন এবং এর বাস্তবায়নগুলি তালিকাভুক্ত করেন। Def এর অর্থ এটি ইন্টারফেসের জন্য ডিফল্ট বাস্তবায়ন। যদি এটি ডিফল্ট না হয় তবে আপনি এটি সনাক্ত করতে ব্যবহৃত ইন্টারফেসের জন্য একটি নাম দিন। অর্থাত্, বিশেষ এবং নামটি হবে IHTTP_Server_sp خصوصی_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 LibraryValues
{
SN_APPLY_LIBRARIES(DEFINE_LIBRARY_ENUM, "")
LastLibrary
};
#define DEFINE_ENTRY_ENUM(I, C, L, D) \
I##_##D##_entry,
এটি ইন্টারফেস বাস্তবায়নের জন্য একটি এনাম তৈরি করে।
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
তারপরে সিপিপি হ'ল,
#include "sn_factory.h"
#include <windows.h>
বাহ্যিক এন্ট্রি পয়েন্ট তৈরি করুন। আপনি depend.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);
}
}
প্রতিটি লাইব্রেরিতে প্রতিটি লাইব্রেরি / এক্সিকিউটেবলের জন্য একটি স্টাব সিপিপি সহ এই "সিপিপি" অন্তর্ভুক্ত থাকে। যে কোনও নির্দিষ্ট সংকলিত শিরোনাম স্টাফ।
#include "sn_pch.h"
এই লাইব্রেরিটি সেটআপ করুন।
#define SN_APPLY_CURRENT_LIBRARY(L, A) \
L(A, sn, "sn.dll")
একটি প্রধান সিপিসি জন্য অন্তর্ভুক্ত। আমার ধারণা এই সিপিপি একটি .h হতে পারে। তবে আপনি এটি করতে পারেন এমন বিভিন্ন উপায় রয়েছে। এই পদ্ধতির আমার জন্য কাজ করে।
#include "../inc/sn_factory.cpp"