From 41b9b4b3bf65af29304bf732fd6e643edf3fcd49 Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Tue, 23 Apr 2024 11:50:47 -0700 Subject: [PATCH] win32_load_time example --- .gitignore | 1 + win32_load_time/build.bat | 26 +++++++++++++++++++++++ win32_load_time/win32_base.c | 11 ++++++++++ win32_load_time/win32_main.c | 38 ++++++++++++++++++++++++++++++++++ win32_load_time/win32_plugin.c | 17 +++++++++++++++ 5 files changed, 93 insertions(+) create mode 100644 .gitignore create mode 100644 win32_load_time/build.bat create mode 100644 win32_load_time/win32_base.c create mode 100644 win32_load_time/win32_main.c create mode 100644 win32_load_time/win32_plugin.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..07ed706 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build/* \ No newline at end of file diff --git a/win32_load_time/build.bat b/win32_load_time/build.bat new file mode 100644 index 0000000..d7e5898 --- /dev/null +++ b/win32_load_time/build.bat @@ -0,0 +1,26 @@ +@echo off + +SET src=%cd% + +cd .. +if not exist "build\" mkdir build +cd build + +REM: ## The arrangement of this build ## +REM: The "base layer" must be built and shared by all dynamic components. +REM: In this example the the base layer is linked via load-time linking with the other modules. +REM: The "plugin" is loaded at run-time. + + + +REM: Build the base layer as a .dll (also produces load-time linking data in win32_base.lib) +cl /nologo /Zi /LD %src%\win32_base.c + + +REM: Build the executable; provide the base layer's load-time linking data via win32_base.lib +cl /nologo /Zi %src%\win32_main.c win32_base.lib + + +REM: Build the plugin as a .dll; provide the base layer's load-time linking data via win32_base.lib +cl /nologo /Zi /LD %src%\win32_plugin.c win32_base.lib + diff --git a/win32_load_time/win32_base.c b/win32_load_time/win32_base.c new file mode 100644 index 0000000..01f2446 --- /dev/null +++ b/win32_load_time/win32_base.c @@ -0,0 +1,11 @@ +// declare base_func; mark it as an exported symbol +__declspec(dllexport) void base_func(void); + +// define base_func +#include +int x = 0; +__declspec(dllexport) void +base_func(void){ + printf("x = %d\n", x); + x += 1; +} diff --git a/win32_load_time/win32_main.c b/win32_load_time/win32_main.c new file mode 100644 index 0000000..5f19acc --- /dev/null +++ b/win32_load_time/win32_main.c @@ -0,0 +1,38 @@ +// declare base_func; mark it as a load-time imported symbol +__declspec(dllimport) void base_func(void); + + +// setup plugin_func as a function pointer so that it can be linked at run time +typedef void PLUGIN_Func(void); +PLUGIN_Func *plugin_func = 0; + + +// need to include for LoadLibraryA/LoadLibraryW and GetProcAddress +#include + +// helper macro for GetProcAddress that handles the casting of function pointers +#define GET_PROC(var,mod,name) *((FARPROC*)(&(var))) = GetProcAddress((mod),(name)) + + +int main(){ + + // functions linked by load-time linking can be called directly without further setup + base_func(); + + + // to call a function with run-time linking, we must manually load and link it + HMODULE module = LoadLibraryA("win32_plugin.dll"); + if (module != 0){ + GET_PROC(plugin_func, module, "plugin_func"); + } + + + // calls to plugin_func only work after the "plugin" loaded successfully + if (plugin_func != 0){ + plugin_func(); + } + + + // demonstration: the data structures contained in the 'base' are not duplicated in each binary + base_func(); +} diff --git a/win32_load_time/win32_plugin.c b/win32_load_time/win32_plugin.c new file mode 100644 index 0000000..2117f48 --- /dev/null +++ b/win32_load_time/win32_plugin.c @@ -0,0 +1,17 @@ +// declare base_func; mark it as a load-time imported symbol +__declspec(dllimport) void base_func(void); + +// declare plugin_func; mark it as an exported symbol +__declspec(dllexport) void plugin_func(void); + +// define plugin_func +#include +__declspec(dllexport) void +plugin_func(void){ + printf("provided by plugin: {\n"); + printf(" "); + base_func(); + printf(" "); + base_func(); + printf("}\n"); +}