I've seen a few examples of how to do this from C++ an unmanaged dll, to a C++ managed CLR dll. I currently have a C++ dll (NetPcapWrap), that references a C dll (npcap.dll). Since the npcap.dll is written in C I cannot compile with CLR so NetPcapWrap is unmanaged. My .Net Forms application references the NetPcapWrap.dll using pInvoke to gets information from the npcap.dll.
Within the npcap.dll is a looping function that writes out data to std::out what I need to do instead call a delegate of the .Net windows Forms app.
I've seen one potential solution https://www.codeproject.com/tips/695387/calling-csharp-net-methods-from-unmanaged-c-cplusp but this would require yet another dll that is compiled with CLR enabled.
Is there a way to do "reverse" pInvoke from an unmanaged C++ dll to a .Net Winforms application?
Sorry, I don't have any code to post because I can't figure out how to write the potion. I can share how I pInvoke the C++ dll but that is not my question.
Thanks
you need the C# code to send a delegate to a C function that expects a function pointer, then store it in some global.
and C# needs to also store this delegate in a static variable to prevent the GC from cleaning it.
on C/C++ side.
// C++ file
using myfunctype = void (*)(void);
// replace with typedef in C
// typedef void (*myfunctype)(void);
extern "C"
__declspec( dllexport )
myfunctype func1;
myfunctype func1 = 0;
extern "C"
__declspec( dllexport )
int SetFunction(myfunctype func_ptr)
{
func1 = func_ptr;
return 5;
}
extern "C"
__declspec( dllexport )
int CallFunction()
{
func1();
return 5;
}
then on C# side
// csharp file
using System.Runtime.InteropServices;
namespace myspace;
public delegate void CFunc();
public class NativeLib
{
public static void CsharpFunc()
{
Console.WriteLine("hello world from Csharp!");
}
public static CFunc func_static = CsharpFunc;
[DllImport("Clib", CallingConvention = CallingConvention.Cdecl)]
public static extern int SetFunction(CFunc func);
[DllImport("Clib", CallingConvention = CallingConvention.Cdecl)]
public static extern int CallFunction();
}
then your main app needs to call them.
// csharp calling application
using myspace;
class Program
{
public static int Main(String[] args)
{
NativeLib.SetFunction(NativeLib.func_static);
NativeLib.CallFunction();
return 0;
}
}
as a bonus, this also works on linux/macos where managed C++ dlls don't exist. (tested with dotnet 6 and 8)
while this small example works, you may need to pin any involved C# object from moving using GCHandle.
note that you cannot allow C++ exceptions to leak into C#, you also cannot allow C# exceptions to leak into C++.