Reputation: 876
I have a native class which receives an std::function as a parameter and at some point in time it calls this callback:
class NativeClass
{
public:
NativeClass(std::function<void(int, const char*)> callback) : m_callback{callback}
{
}
void DoAction()
{
...
m_callback(3, "asd");
...
}
private:
std::function<void(int, const char*)> m_callback;
}
Let's say this resides in a library which is out of my control, so std::function is a given.
Now I have a C++/CLI class where I would like thiss callback to be called:
public ref class ManagedConsumer()
{
public:
ManagedConsumer()
{
m_nativeClass = new NativeClass(std::bind(&ManagedConsumer::OnCallback, this); // errors: 3374, 2672
m_nativeClass = new NativeClass([this](...){this->OnCallback(...);}); // errors: 3374, 2672
}
void OnCallback(int i, const char* str)
{
localInt += i; // must access local variable from this
// consume callback
}
private:
NativeClass *m_nativeClass;
int localInt;
}
Is it even possible to capture the this variable? I cant really change the NativeClass to pass an Interface or something different.
Upvotes: 0
Views: 962
Reputation: 21
you need to use a bit of marshalling over here, as well need to make callback as an delegate.
Content of managed class .h
#pragma once
using namespace System::Runtime::InteropServices;
public delegate void CallbackDelegate(int data);
public ref class ManagedClass
{
UnmanagedClass* unmanagedClassPtr;
[MarshalAsAttribute(UnmanagedType::FunctionPtr)]
CallbackDelegate^ _Delegate;
public:
ManagedClass()
{
unmanagedClassPtr = new UnmanagedClass();
_Delegate = gcnew CallbackDelegate(this, &ManagedClass::MyCallback);
auto ptr = Marshal::GetFunctionPointerForDelegate(_Delegate).ToPointer();
unmanagedClassPtr->setCallback(ptr);
}
virtual ~ManagedClass()
{
delete unmanagedClassPtr;
}
void MyCallback(int s) {
System::Console::WriteLine("hello from unmanaged");
};
};
Content of unmanaged class .h
#pragma once
#include "callbackType.h"
class UnmanagedClass
{
public:
void setCallback(void* _callback)
{
callback = (callbackType)_callback;
callback(13);//call it immediately
};
};
I got this working from next sources: https://www.codeproject.com/Articles/9903/Calling-Managed-Code-from-Unmanaged-Code-and-vice and C++/CLI delegate as function pointer (System.AccessViolationException)
Upvotes: 2