从参数传递的函数提取参数及RunInMainThread多参数优化问询
RunInMainThread with Parameter Binding and Variable Arguments (C03/CBuilder) Let's break down how to fix both your issues: eliminating the need for the redundant fP1 parameter, and adding support for variable arguments—all without C++11 features like <functional> or lambdas.
1. Eliminate Redundant Parameter Passing
Your current code requires manually passing fP1 to initialize the struct's P1 field. We can use C++03 templates to automatically deduce the parameter type and bundle it with the closure function, no extra manual parameter setup needed.
Optimized Single-Parameter Version
template <typename TParam> void Class2::RunInMainThread(void(__closure* FuncToCall)(TParam), TParam param) { struct Args { TParam P1; void(__closure* F)(TParam); void __fastcall FTC() { F(P1); } } args = {param, FuncToCall}; TThread::Synchronize(NULL, &args.FTC); }
Now you can call it cleanly, no need to worry about matching parameter types explicitly:
void Class1::MainThreadFunction(const __int64 param) { if(GetCurrentThreadId() != System::MainThreadID) { RunInMainThread(MainThreadFunction, param); return; } // ... rest of your main thread logic }
The template automatically deduces TParam as const __int64, so you avoid repeating types and redundant parameter handling.
2. Add Support for Variable Arguments
Since C++03 doesn't have variadic templates, we'll implement overloaded versions of RunInMainThread for different argument counts (0, 1, 2, 3, etc.—extend as needed for your use case).
Full Overloaded Implementation
// 0-parameter version void Class2::RunInMainThread(void(__closure* FuncToCall)()) { struct Args { void(__closure* F)(); void __fastcall FTC() { F(); } } args = {FuncToCall}; TThread::Synchronize(NULL, &args.FTC); } // 1-parameter version template <typename T1> void Class2::RunInMainThread(void(__closure* FuncToCall)(T1), T1 p1) { struct Args { T1 P1; void(__closure* F)(T1); void __fastcall FTC() { F(P1); } } args = {p1, FuncToCall}; TThread::Synchronize(NULL, &args.FTC); } // 2-parameter version template <typename T1, typename T2> void Class2::RunInMainThread(void(__closure* FuncToCall)(T1, T2), T1 p1, T2 p2) { struct Args { T1 P1; T2 P2; void(__closure* F)(T1, T2); void __fastcall FTC() { F(P1, P2); } } args = {p1, p2, FuncToCall}; TThread::Synchronize(NULL, &args.FTC); } // 3-parameter version (extend as needed for more arguments) template <typename T1, typename T2, typename T3> void Class2::RunInMainThread(void(__closure* FuncToCall)(T1, T2, T3), T1 p1, T2 p2, T3 p3) { struct Args { T1 P1; T2 P2; T3 P3; void(__closure* F)(T1, T2, T3); void __fastcall FTC() { F(P1, P2, P3); } } args = {p1, p2, p3, FuncToCall}; TThread::Synchronize(NULL, &args.FTC); }
How It Works
- Each overload handles a specific number of arguments, matching the signature of the closure you want to run.
- The nested
Argsstruct captures both the closure function and its parameters, storing them until the main thread is ready to execute. - The
FTCmethod acts as a trampoline: it invokes the saved closure with the stored parameters whenTThread::Synchronizeruns it on the main thread.
Key Notes
- __closure is C++Builder-specific: This code relies on C++Builder's
__closurekeyword, which represents a member function pointer that includes thethispointer (a closure). - No C++11 required: All code uses only C++03 features, strictly adhering to your constraints.
- Extensibility: Add more overloads if you need support for functions with more than 3 parameters.
内容的提问来源于stack exchange,提问作者Coder12345

