我正在开发一个基于插件的系统,该系统使用插件的共享库。我想在这些库中设置一些静态变量,以便我可以在各个地方使用它们,包括全局构造函数。我可以从共享库中的主可执行文件调用一个函数,使其在所述共享库中的全局构造函数之前运行吗?无论我使用共享内存还是通过将静态变量传递给共享库来注册静态变量,此设置代码都会在 dll 中的全局构造函数之后发生。
为了进一步了解上下文,一些用例是:记录器、分配器和控制台变量/cvar。这些系统都在程序中普遍使用,我希望能够使用这些全局构造函数中的静态变量。特别是,AutoCvars 是一种常见的用例,可以从文件中使用特定的“变量”,为了简单起见,它被放置在全局空间中,以便它可以立即获取数据,并在应用程序的生命周期中生存: https://vkguide.dev/docs/extra-chapter/cvar_system/
这是一个代码示例:
分配器.hpp
#pragma once
class Allocator {
public:
static Allocator* GetAllocator();
static void SetAllocator(Allocator* allocator);
void* Allocate(size_t size);
size_t GetUsedSize() const;
protected:
static Allocator allocatorSingleton;
size_t usedSize = 0;
};
分配器.cpp:
#include "Allocator.hpp"
static Allocator* allocatorState = nullptr;
Allocator* Allocator::GetAllocator() {
return allocatorState;
}
void Allocator::SetAllocator(Allocator* allocator) {
allocatorState = allocator;
}
void* Allocator::Allocate(size_t size) {
// ALLOCATION OCCURS HERE
usedSize += size;
return nullptr;
}
size_t Allocator::GetUsedSize() const {
return usedSize;
}
主要.cpp:
#include <iostream>
#include <Windows.h>
#include "Allocator.hpp"
int main() {
HINSTANCE dllHandle = LoadLibrary(L"Library.dll");
if (!dllHandle) {
printf("Could not load the dynamic library.\n");
return EXIT_FAILURE;
}
Allocator allocator;
Allocator::SetAllocator(&allocator);
printf("Allocated Size Before: %zu.\n", allocator.GetUsedSize());
auto fn = reinterpret_cast<void(*)(Allocator*)>(GetProcAddress(dllHandle, "RegisterAllocator"));
if (!fn) {
printf("Could not locate the function.\n");
return EXIT_FAILURE;
}
fn(&allocator);
printf("Allocated Size After: %zu.\n", allocator.GetUsedSize());
return 0;
}
DllMain.cpp:
#include "../CVarTest/Allocator.hpp"
class SampleClass {
public:
SampleClass() {
Allocator::GetAllocator()->Allocate(42);
}
};
// Here, SampleClass doesn't work, and causes an error. This is what I want to get working.
SampleClass myInstance;
extern "C" {
void __declspec(dllexport) RegisterAllocator(Allocator* sourceAllocator) {
Allocator::SetAllocator(sourceAllocator);
// Here, SampleClass does work, and the final usedSize is 42.
// SampleClass myInstance;
}
}
正如其他人提到的,您尝试执行此操作的方式可能是错误的。
我之前使用过 DLL,像您一样加载动态插件。我发现按照您的要求做某事的一个解决方案是具有共同的依赖关系。
+-------------+
| Main |
| Application +----- Load DLL ---+
| (.exe) | |
+-----+-------+ v
| +-----------+
v | |
+-------------+ +-----+ My Plugin |
| | | | |
| Utils |<-----+ +-----------+
| (.dll) |
+-------------+
现在,“Utils”可以包含您想要在“我的插件”以及“主应用程序”中使用的必要工具:类、全局变量等。这非常有效,因为在加载插件时已经加载了“Utils”,并且在加载“我的插件”时其全局变量已按预期初始化。
(即,即使多个 DLL 或插件需要,依赖项也仅加载一次。)