
Um mapeador PE minimalista que carrega DLLs diretamente da memória e chama uma interface de plugin limpa, sem necessidade de LoadLibrary.
Um mapeador PE reflexivo minimalista com uma interface de plugin hot-swappable para Windows x64. Mapeia uma DLL diretamente de um buffer de bytes na memória, resolve suas exportações e chama uma ABI IPlugin limpa sem tocar em LoadLibrary. Código complementar para o post do blog sobre loaders reflexivos e arquiteturas de plugins modulares.
Veja o artigo completo: Using Reflective Loaders to Replace LoadLibrary for Hot-Swappable Modules in C++
# Configure
cmake -B build
# Build
cmake --build build --config Release
# The build produces:
# build/Release/cmdplugin.dll (example plugin)
# build/Release/harness.exe (test harness)
# Map cmdplugin.dll from disk, run "dir C:\"
harness.exe cmdplugin.dll "dir C:\"
# Default: loads cmdplugin.dll, runs "whoami"
harness.exe
O harness lê a DLL em um buffer de bytes, mapeia-a com o loader reflexivo, resolve as exportações do plugin e despacha o comando através da interface IPlugin.
ReflectivePluginLoader/
├── CMakeLists.txt # Root build
├── Include/
│ ├── IPlugin.h # Plugin ABI (TaskApi, IPlugin, helpers)
│ └── ReflectiveLoaderEngine.h # PE mapper + export resolver
├── Modules/
│ └── CmdPlugin/
│ ├── cmdplugin.cpp # Example: command execution plugin
│ └── CMakeLists.txt
├── Testing/
│ ├── main.cpp # Test harness (loads DLL from file)
│ └── CMakeLists.txt
└── Tools/
└── file2hex.py # Convert a DLL to a C byte array
Modules/.IPlugin.h e implemente a interface IPlugin:#include "IPlugin.h"
class MyPlugin : public IPlugin {
public:
void init() const override { /* setup */ }
void execute(TaskApi* task) const override { /* do work */ }
void cleanup() const override { /* teardown */ }
};
Implemente as cinco funções exportadas (create_plugin, destroy_plugin, plugin_init, plugin_exec, plugin_cleanup) usando HeapAlloc/placement new para alocação cross-module segura para a CRT.
Adicione um CMakeLists.txt e registre-o no CMakeLists.txt raiz com add_subdirectory().
O host não precisa saber o que seu módulo faz internamente. Ele mapeia, resolve, chama init -> execute -> cleanup e segue em frente.
O mapeador lida com o básico e deliberadamente para por aí:
Se um módulo precisar de qualquer um desses, estenda o mapeador ou rejeite o módulo antecipadamente com um erro claro. Suporte parcial silencioso é o pior modo de falha.