Reputation: 1529
I am using Robert Giesecke's Unmanaged Exports to call functions in my C# managed dll from my native C++ application. I now need to somehow pass a function pointer from my C++ application to the C# dll so that my dll can do a callback into c++. This has got me stumped.
C++
//Normal call to CSharp dll using Unmanaged Exports
FString UHostBridgeComponent::DoCallToCCsharp()
{
FString filePath = FPaths::Combine(*FPaths::GamePluginsDir(), TEXT("ThirdParty"), TEXT("CSharp.dll"));
void *DLLHandle = NULL;
if (FPaths::FileExists(filePath))
{
DLLHandle = FPlatformProcess::GetDllHandle(*filePath); // Retrieve the DLL.
}
if (DLLHandle != NULL)
{
_DoTest DLLFuncPtr = NULL;
FString procName = "DoTest";
DLLFuncPtr = (_DoTest)FPlatformProcess::GetDllExport(DLLHandle, *procName);
if (DLLFuncPtr != NULL)
{
const char* result = DLLFuncPtr(false);
FString output(result);
return output;
}
}
return "";
}
C#
//Function called from C++ application
[DllExport("DoTest", CallingConvention = CallingConvention.StdCall)]
public static string DoTest(bool result)
{
//Do processing
//...
string result = "this is the result string";
return result;
}
I would imagine that I need to pass a pointer to a function in C++ when calling a function in C#.
const char * result = DLLFuncPtr(pointerToMyFunction);
That pointer must be saved to a variable in C# and executed as callback when the C# dll wants to send data to the c++ application.
I am unsure how to define these functions and variables. Any help would be appreciated.
Upvotes: 2
Views: 860
Reputation: 1529
I managed to figure it out myself. See below the answer
C++
//Function pointer typedef
typedef bool(*functionPointer)(const char* data);
//the actual function that gets pointed to
bool UHostBridgeComponent::realFunction(const char * data)
{
FString output(data);
UE_LOG(LogEGM, Log, TEXT("CALLBACK FUNCTION data= %s"), *output);
return true;
}
//function pointer as variable (not yet pointing to realFunction)
functionPointer myFunc;
//function to call in C# that passes the function pointer
typedef bool(*_DoSendCallbackFunction)(functionPointer callback);
bool UHostBridgeComponent::DoCallbackTest()
{
FString filePath = FPaths::Combine(*FPaths::GamePluginsDir(), TEXT("ThirdParty"), TEXT("CSharp.dll"));
void *DLLHandle = NULL;
if (FPaths::FileExists(filePath))
{
DLLHandle = FPlatformProcess::GetDllHandle(*filePath);
}
if (DLLHandle != NULL)
{
_DoSendCallbackFunction DLLFuncPtr = NULL;
FString procName = "DoSendCallbackFunction";
DLLFuncPtr = (_DoSendCallbackFunction)FPlatformProcess::GetDllExport(DLLHandle, *procName);
if (DLLFuncPtr != NULL)
{
myFunc = &realFunction; //point myFunc to the function realFunction
return DLLFuncPtr(myFunc);
}
}
return false;
}
C#
public delegate bool FooDelegate(string data);
[DllExport("DoSendCallbackFunction", CallingConvention = CallingConvention.StdCall)]
public static bool DoSendCallbackFunction(IntPtr callback)
{
FooDelegate myFooDelegate = (FooDelegate)Marshal.GetDelegateForFunctionPointer(callback,typeof(FooDelegate));
string theString = "This is the data!!";
myFooDelegate(theString);
return true;
}
and the result is printed to my log file:
LogEGM: CALLBACK FUNCTION data= This is the data!!
Upvotes: 1