Ohne die C++ Deklaration deines Funktionszeigers zu kennen und wie sich das Array zusammensetzt, kann man schlecht weiterhelfen.
Generell muss man bei so einem Reverse Interop allerdings ein paar Dinge beachten.
1. Die Callilng Convention muss passen
2. Die Parameter müssen stimmen (bei Arrays nicht ganz einfach)
3. Die Delegate Instanz muss erreichbar bleiben, da sie sonst vom Garbage Collector eingesammelt wird, während der zugehörige Funktionszeiger auf der C++ Seite noch in Gebrauch ist (Den Funktionszeiger, der von Marshal::GetFunctionPointerForDelegate zurückgegben wird, muss man allerdings nicht pinnen)
Wie die Deklaration des Delegates aussehen muss, kommt darauf an wie der Funktionszeiger in der deiner C++ Bibliothek deklariert ist und wie sich das Array zusammensetzt. Ich mach mal ein einfaches Beispiel: (Bin allerdings nicht so firm mit der C++/CLI Syntax, deshalb bitte nicht gleich copy und pasten)
Nehmen wir an, es gibt folgenden C++ Code
Code: Alles auswählen
// Im header
typedef void (*FunctionPointer)(int args[]);
void invoke(FunctionPointer func);
// In cpp Datei
void invoke(FunctionPointer func)
{
int[] nums = {1, 2, 3, 4};
func(nums);
}
Dann sieht das entsprechende Delegate für
FunctionPointer in C++/CLI so aus:
Code: Alles auswählen
[UnmanagedFunctionPointer (CallingConvention::Cdecl)]
delegate void CallbackFunc ([MarshalAs(UnmanagedType::LPArray, SizeConst = 4)] array<int>^ args);
Die Calling Convention wird hier mit Cdecl angegeben, weil das die Standard-Konvention in C++ ist, wenn der Funktionszeiger nicht explizit als __stdcall deklariert wird. Managed Arrays haben eine vorgegebene Länge, allerdings weiß der Interop Marshaler nicht wie groß das C++ Array ist, weshalb man dies mit SizeConst angeben muss. Wenn die Größe erst zur Laufzeit bekannt ist, muss man zusätzlich einen Längen Parameter einführen und den
SizeParamIndex angeben.
Auf der C++/CLI Seite lässt sich das folgendermaßen aufrufen
Code: Alles auswählen
// header der C++ Lib einbinden
void TheClass::invokeCallback(CallBackFunc^ theCallback)
{
auto funcPtr = static_cast<FunctionPointer>(Marshal::GetFunctionPointerForDelegate(theCallback).ToPointer());
// Aufruf der C++ Funktion
invoke(funcPtr);
// Sorgt dafür, dass das Delegate nicht vorzeitig vom Garbage Collector eingesammelt wird
GC::KeepAlive(theCallback);
}
Wenn der Aufruf deines Callbacks asynchron ist oder deine C++ Bibliothek den Funktionszeiger über längere Zeit speichert, solltest du das Delegate in deiner Wrapper Klasse als Member speichern.