Reputation: 1182
I have this code in a plain C static library:
extern "C" {
typedef void (__cdecl* VisitChildren)(Option*);
void __cdecl DoVisitChildren(Children* List, VisitChildren Visitor);
}
And I'm trying to use it from some C++ code (unit tests) using a lambda.
...
DoVisitChildren(children, [&] (Option* option) {
...
});
I'm getting the compiler error C2664 ... cannot convert parameter 2 from 'unittests::UnitTest1::TestBuild::<lambda_b286d160b9bab3e09ab93cd59fc49f0b>' to 'VisitChildren'
If I remove the capture '&' it compiles and works, but I need to capture some bits and bobs.
Is this possible?
Upvotes: 0
Views: 340
Reputation: 171263
A closure created by a lambda expression can be implicitly converted to a function pointer, but only if it does not capture any variables. Also, it will be converted to a pointer to an extern "C++"
function, not an extern "C"
function, and technically those are incompatible types.
So no, you can't do this.
A hacky workaround is to store your actual closure in a global variable and pass a callback which invokes it. This will only work if your program is single-threaded and the DoVisitChildren
call does not store the callback for later use.
std::function<void(Option*)> callback;
extern "C" void __cdecl invoke_callback(Option* o) { callback(o); }
// ...
callback = [&] (Option* option) { /* ... */ };
DoVisitChildren(children, invoke_callback);
Upvotes: 2