Reputation: 13195
I have a CLI wrapper to a C++ class. The C++ class has a callback that passes a char* array, and the length of that array.
void (CPP_CALLBACK*)(char* data, unsigned int dataLength)
In C# land, I have this callback
private delegate void AppPacketReceivedDelegate(byte[] data);
My CLI wrapper receives the CPP_CALLBACK callback, and must then somehow call the C# delegate.
Any ideas on how to do this ? I tried
System::Action<cli::array<char>^>
but I am not sure how to match the delegate to this Action.
Update:
I convert the delegate into a function pointer, and then I can call the function pointer from CLI using this syntax:
typedef void(__stdcall * WRAPPER_APP_PACKET_CALLBACK) (cli::array<unsigned char>^);
But, when I call this, the array is always of size 1 !
Upvotes: 2
Views: 361
Reputation: 63
Here a simple example, not exactly matching your situation, but it could be quickly adapted.
CppClass.h
namespace MyCppNamespace
{
typedef void (__stdcall *callback_function)(int, const char*);
class CppClass
{
private:
callback_function _callbackFunc;
public:
void DoSomething(callback_function callbackFunc);
}
}
DotNetClass.cs
namespace MyManagedNamespace
{
public delegate void ManagedCallback(int size, string message);
}
CliWrapperClass.h
#include "CppClass.h"
using namespace MyManagedNamespace;
namespace MyCliNamespace
{
public ref class CliWrapperClass
{
private:
CppClass *_cppClass;
public:
void DoSomething(ManagedCallback ^ callback);
}
}
CliWrapperClass.cpp
#include "CliWrapperClass.h"
namespace MyCliNamespace
{
void CliWrapperClass::DoSomething(ManagedCallback ^ callback)
{
System::IntPtr callbackPtr = System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(callback);
_cppClass->DoSomething(static_cast<callback_function>(callbackPtr.ToPointer()));
}
}
In the .Net class, you can create an instance of CliWrapperClass
and call its DoSomething(...)
function in this way:
namespace MyManagedNamespace
{
public class ManagedClass
{
private ManagedCallback _callback = MyCallback;
private void MyCallback(int size, string message)
{
// Do what you want ...
}
public void MyFunction()
{
CliWrapperClass wrapper = new CliWrapperClass();
wrapper.DoSomething(_callback);
}
}
}
Upvotes: 1
Reputation: 13195
In the end, I marked the C# class and the corresponding delegate as unsafe
, and
then I was able to call the delegate from C++ and pass over the C-style array. On the C# side, I created a managed array and copied the bytes over using Marshal.Copy
Upvotes: 0