【问题标题】:How to pass a string from C++-CLI to C# via C++-CLI callbacks and delegates如何通过 C++-CLI 回调和委托将字符串从 C++-CLI 传递到 C#
【发布时间】:2011-04-26 00:03:08
【问题描述】:

我有一个围绕从 C# 调用的标准 C++ 库的 C++-CLR 包装器。为了从库中接收状态消息,我使用通过 Marshal::GetFunctionPointerForDelegate 分配给 C++ 代码中的回调的委托。

我花了很长时间才开始工作,而且我非常非常接近(我认为)。调用了 C# 委托,但字符串未正确跨边界传递。

当我从 C++ 代码中调用 TakesCallback("Test String") 时,我只会在 C# 函数中返回垃圾。

---原始C++类和回调函数---

class Solver
{
    private:

    std::string TakesCallback(const std::string message) 
    {
        return cb(message);
    }

    public:

    // Declare an unmanaged function type that takes a string
    typedef std::string (__stdcall* ANSWERCB)(const std::string);
    ANSWERCB cb;
};

--- 从托管包装器设置回调的函数----

// Set the delegate callback
void ManagedSolver::SetMessageCallback(SendMessageDelegate^ sendMessageDelegate)
{
    _sendMessage = sendMessageDelegate;

    // Use GetFunctionPointerForDelegate to get the pointer for delegate callback
    IntPtr ip = Marshal::GetFunctionPointerForDelegate(sendMessageDelegate);
    _solver->cb = static_cast<Solver::ANSWERCB>(ip.ToPointer());
} 

--- C# 函数传递给 C++\CLR 包装器 SetMessageCallBack ----

private void Message(string message)
{
    XtraMessageBox.Show(message, "Done", MessageBoxButtons.OK);
}

【问题讨论】:

  • 您确定您的意思是托管 C++? (我认为)Visual Studio 2003 不再支持 C++ 的托管扩展。C++/CLI 是它的替代品,它是一种完全不同的语言......
  • 嗨,比利,对不起,你当然是对的。我的包装器是围绕标准 C++ 库的 C++/CLR。我已经更新了标题和正文。
  • 好的,我已经解决了,std::string 不能与互操作一起使用,因为这里声明了多种实现stackoverflow.com/questions/874551/stdstring-in-c,只要 StackOverflow 允许我,我就会回来回答这个问题到。
  • 传递 message.c_str() 代替,与默认编组兼容。
  • 谢谢汉斯,这对我有用。

标签: c# visual-c++ callback c++-cli interop


【解决方案1】:

我已经使用the code from this page 几个月了,我觉得它非常好。它只是一个可以跨项目复制的头文件,它可以快速而干净地完成工作。

你用例如

std::wstring s = clix::marshalString<E_UNICODE>(myCliString);

System::String^ s = clix::marshalString<E_ANSI>(mystdstring);

它可以双向工作,让您指定所需的编码(ANSI、UTF8 或 Windows 的 unicode——实际上是 UTF16)。

【讨论】:

    【解决方案2】:

    C++ std::string 和 .NET System::String 不可互换。 C# 不能使用第一个,本地 C++ 代码不能使用第二个。您需要的是一个接受std::string 并在调用委托之前将其转换为System::String^ 的C++/CLI 函数。

    【讨论】:

      【解决方案3】:

      一般来说,std c++ 类不能与 C# 进行封送处理。如果您将 C++ 代码构建为 Unicode,我建议您将代码更改为以下内容:

      C++

      // Declare an unmanaged function type that takes a string
      typedef int (__stdcall* ANSWERCB)(LPCTSTR);
      

      C#

      private void Message([MarshalAs(UnmanagedType.LPWStr)]string message)
      {
          XtraMessageBox.Show(message, "Done", MessageBoxButtons.OK);
      }
      

      看看下面example from MSDN

      【讨论】:

        【解决方案4】:

        C++(非托管)

        class DllContext
        {
        public:
        typedef void (__stdcall *LOG_CALLBECK)(const wchar_t* LogString);
        DllContext(LOG_CALLBECK WriteLog) // Constructor
        {
            this->WriteLog = WriteLog;
            this->WriteLog(L"Creating сontext..."); // UNICODE string!
        }
        
        private:
        LOG_CALLBECK WriteLog;
        }
        
        // Export function
        SENDAUDIOCLIENT_API DllContext *CreateContext(DllContext::LOG_CALLBECK WriteLog)
        {
            return new DllContext(WriteLog);
        }
        

        C#

        class MyClass
        {
        private delegate void WriteLog_Delegate([MarshalAs(UnmanagedType.LPWStr)]string Mess);
        private WriteLog_Delegate WriteLog;
        
        [DllImport("My.dll", EntryPoint = "?CreateContext@@YAPAVDllContext@@P6GXPB_W@Z@Z", CallingConvention = CallingConvention.Cdecl)]
        private static extern IntPtr CreateContext(WriteLog_Delegate WriteLogProc);
        
        private IntPtr Context = IntPtr.Zero;
        
        public MyClass()
        {
            this.WriteLog = new WriteLog_Delegate(this.WriteLogToConsole);
                this.Context = CreateContext(this.WriteLog);
        }
        
        private void WriteLogToConsole(string Mess)
        {
            Console.WriteLine("Message from unmanaged code: {0}", Mess);
        }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-02-27
          • 1970-01-01
          • 2023-03-19
          • 1970-01-01
          相关资源
          最近更新 更多