如何使用非托管导出从c++发送函数指针到c# dll以用作回调

本文关键字:指针 函数 dll 回调 何使用 c++ | 更新日期: 2023-09-27 18:02:20

我使用Robert Giesecke的非托管导出从我的本地c++应用程序调用c#托管dll中的函数。我现在需要以某种方式将函数指针从我的c++应用程序传递到c# dll,以便我的dll可以回调到c++。这把我难住了。

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;
    }

我想在c#中调用函数时,我需要在c++中传递一个指向函数的指针。

const char * result = DLLFuncPtr(pointerToMyFunction);

该指针必须保存到c#中的变量中,当c# dll想要向c++应用程序发送数据时,作为回调执行。

我不确定如何定义这些函数和变量。

如何使用非托管导出从c++发送函数指针到c# dll以用作回调

我自己想明白了。请看下面的答案

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;
    }

,结果被打印到我的日志文件:

LogEGM: CALLBACK FUNCTION data= This is the data!!