封装C++ DLL以记录指定函数调用的可行性及更优方案问询
Great questions! Let’s break this down clearly, as someone who’s done this kind of instrumentation plenty of times.
Absolutely—this is a standard pattern for adding instrumentation (like call timing) when you have the original DLL’s header and import library (.lib). Here’s how to pull it off:
Step 1: Set up your wrapper project
- Spin up a new C++ DLL project in your IDE (Visual Studio, Clion, etc.).
- Link against the original DLL’s
.libfile so your wrapper can directly call the original functions. - Include the original DLL’s header to get exact function signatures—critical to avoid mismatches.
Step 2: Write wrapped functions
For every function you want to track, define a function with the exact same signature as the original. Inside each wrapper:
- Log the start time (use
std::chronofor high-precision timing, orGetSystemTimeif you prefer Win32 APIs). - Call the original function (use the global scope operator
::to avoid name collisions with your wrapper). - Log the end time/duration before passing the result back to the caller.
Here’s a quick code example:
#include "OriginalDLL.h" #include <chrono> #include <fstream> #include <iostream> // Wrapper for OriginalFunc(int) from the original DLL void OriginalFunc(int param) { // Log call start auto start = std::chrono::high_resolution_clock::now(); std::ofstream log("call_timing.log", std::ios::app); log << "[START] OriginalFunc called at: " << std::chrono::system_clock::to_time_t(start) << "\n"; // Forward to the original function ::OriginalFunc(param); // Log call duration auto end = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start); log << "[END] OriginalFunc took: " << duration.count() << " microseconds\n"; }
Step 3: Replace the original DLL
- Rename your wrapper DLL to match the original’s filename (e.g., if the original is
MyBigDLL.dll, name your wrapperMyBigDLL.dll). - Keep the original DLL in a location your wrapper can access—either place it in a subfolder and use
LoadLibrarywith a full path, or just put both in the same directory (the wrapper will load the original when it needs to). - When the target app loads the DLL, it’ll pick up your wrapper instead, which handles logging before forwarding calls.
If you only care about a tiny subset of functions in a huge DLL, building a full wrapper is overkill. Here are two far lighter options:
1. Function hooking (detours)
Instead of wrapping every function, use function hooking to intercept only the ones you care about. Tools like Microsoft Detours make this straightforward, or you can implement basic hooking with inline assembly (for x86/x64) if you want to avoid external libraries.
How it works:
- Redirect the target function’s entry point to your custom "hook" function.
- Your hook logs the timing, calls the original function (via a saved pointer to the original entry), then returns the result.
Simplified example with Detours:
#include <detours.h> #include "OriginalDLL.h" #include <chrono> #include <fstream> // Pointer to the original function void(*OriginalFuncPtr)(int) = ::OriginalFunc; // Our hooked function void HookedOriginalFunc(int param) { auto start = std::chrono::high_resolution_clock::now(); // Call the original function OriginalFuncPtr(param); auto end = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start); std::ofstream log("hook_timing.log", std::ios::app); log << "OriginalFunc took " << duration.count() << "ms\n"; } // Initialize the hook (call this early in your app/wrapper) void SetupHook() { DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); DetourAttach(&(PVOID&)OriginalFuncPtr, HookedOriginalFunc); DetourTransactionCommit(); }
This is perfect for targeting 2-3 functions in a DLL with hundreds—no need to wrap everything.
2. Runtime instrumentation tools
If you don’t want to write any code at all, use existing tools to instrument functions on the fly:
- Visual Studio Profiler: Built into VS, it can track function call times and performance metrics without modifying code. Just attach it to your target app and select the functions you want to monitor.
- frida: A dynamic instrumentation toolkit that lets you write JavaScript scripts to hook native DLL functions. Great for quick testing—no compilation needed.
- Intel VTune: A more advanced profiler for deep performance analysis, including specific function timing.
These tools are ideal if you just need to collect data temporarily and don’t want to maintain custom code.
内容的提问来源于stack exchange,提问作者James Driver

