Cześć. Mam taki kod, chodzi o wykorzystanie paru obiektów (a konkretniej ich wirtualnych funkcji) z jakiejś zewnętrznej biblioteki. Mam kilkadziesiąt takich interfejsów, każda klasa jest przypisana tylko do jednego obiektu (SomeAbstractInterface -> whatever). initialize_interfaces i terminate_interfaces musi być wykonany w specyficznym momencie podczas wykonywania programu, nie mogę zrobić tego na samym początku.
I teraz pytanie, czy da się tu coś uprościć/poprawić. Docelowo chciałbym pozbyć się konieczności trzymania module_name, interface_name i all_instances w pamięci, wszystko to znane jest już w czasie kompilacji i nic się tu nie zmienia.
Mniej więcej coś takiego chciałbym otrzymać w ostatecznym kodzie:
class SomeAbstractInterface {
public:
virtual void unknown00();
virtual void unknown01();
virtual void unknown02();
virtual void unknown03();
virtual void unknown04();
virtual void unknown05();
};
// ...
static SomeAbstractInterface * whatever = nullptr
// ...
void initialize_interfaces() {
whatever = find_interface("module.dll", "interface_abc");
// ...
}
Jak coś takiego osiągnąć w jakiś sprytniejszy sposób, nie robiąc tego co w powyższym kodzie ręcznie? Tak jak wspominałem tych interfejsów jest kilkadziesiąt więc nie byłoby to zbyt czytelne/łatwe w modyfikacji.
To co teraz mam:
#include <iostream>
#include <string_view>
#include <vector>
#undef interface
void* find_interface(std::string_view module_name, std::string_view interface_name) {
std::cout << module_name << ": " << interface_name;
// ...
return nullptr;
}
class BaseInterface {
public:
BaseInterface(std::string_view _module_name, std::string_view _interface_name)
: module_name(_module_name), interface_name(_interface_name) {
all_instances.push_back(this);
}
void* pointer;
std::string_view module_name;
std::string_view interface_name;
static inline std::vector<BaseInterface*> all_instances;
};
template <typename abstract_interface>
class Interface : public BaseInterface {
using BaseInterface::BaseInterface;
public:
abstract_interface* operator->() {
return reinterpret_cast<abstract_interface*>(pointer);
}
};
void initialize_interfaces() {
for (auto interface : BaseInterface::all_instances) {
interface->pointer = find_interface(interface->module_name, interface->interface_name);
// ...
}
}
void terminate_interfaces() {
for (auto interface : BaseInterface::all_instances) {
interface->pointer = nullptr;
// ...
}
}
class SomeAbstractInterface {
public:
virtual void unknown00();
virtual void unknown01();
virtual void unknown02();
virtual void unknown03();
virtual void unknown04();
virtual void unknown05();
};
// ...
static Interface<SomeAbstractInterface> whatever("module.dll", "interface_abc");
//...
int main(int argc, char** argv) {
// some code
initialize_interfaces();
// some code
whatever->unknown00();
// some code
terminate_interfaces();
// some code
return 0;
}