【问题标题】:Handling Array returned from c++ dll to C#处理从 c++ dll 返回到 C# 的数组
【发布时间】:2026-01-25 03:15:02
【问题描述】:

我在用 c++ 创建的 dll 中有这个

extern "C" __declspec(dllexport)
    char*  __stdcall hh()
{
    char a[2];
    a[0]='a';
         a[1]='b';
    return(a);
}

这就是我尝试在 c# 中处理代码的方式

[DllImport(@"mydll.dll",CharSet = CharSet.Ansi,CallingConvention = CallingConvention.StdCall)]     
       public static extern IntPtr hh();
       static void Main(string[] args)
        {
            IntPtr a = hh();
           //How to proceed here???
        }


    }

帮助进一步进行。

【问题讨论】:

  • 你的问题到底是什么?
  • 我想在 c# 中打印从 c++ 代码返回的数组

标签: c# c++ marshalling


【解决方案1】:

尽量使用非空的StringBuilder作为返回值。

【讨论】:

    【解决方案2】:

    答案是

     string stra = Marshal.PtrToStringAnsi(a);
    

    但您也有问题,即 dll 根据您的代码返回垃圾,因为 char* 是本地 c 样式字符串。 如果你能返回类似的东西就可以了:

     const char* str = "Hello from DLL.";
    

    【讨论】:

    • 我想传递字符串数组而不是单个字符串
    • 好的。误解了那一点。无论如何,希望有所帮助。
    【解决方案3】:

    没有办法处理这样的数组。 char a[2] 在您的 C++ 函数的堆栈上分配,并在您从它返回时立即销毁。您应该从 C# 传递一个数组并将其填充到 C++ 代码中,或者在堆中分配数组并提供一些释放它的方法。

    如果正确,处理将取决于您如何从 C++ 代码返回数据。如果它仍然是 IntPtr,您可以使用 Marshal.ReadByte 方法从内存中读取字符,并在必要时使用 Encoding 方法将这些字节转换为字符串。

    const int bufferSize = 2; // suppose it's some well-known value. IntPtr p = ...; // get this pointer somehow. for (var i = 0; i != bufferSize; ++i) { var b = Marshal.ReadByte(p, i); Console.WriteLine(b); }

    【讨论】:

      【解决方案4】:

      我得到了如下解决方案::

      我们的 C++ 代码如下

      extern "C" __declspec(dllexport)
          char**  __stdcall hh()
      {
       static char* myArray[3] = {"A1", "BB2", "CC3",};
          return myArray;
      }
      

      而C#如下

      [DllImport(@"ourdll.dll",CharSet = CharSet.Ansi,CallingConvention = CallingConvention.StdCall)]     
            public static extern IntPtr hh();
             static void Main(string[] args)
              {
                  IntPtr a = hh();
                  int j = 0;
                  string[] s=new string[100];
                 do
                 {
                     s[j] = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(a,4*j));
                     j++;
                 }
                 while(s[j-1] != null);
              }
      

      现在面临的唯一问题是我们如何知道数组的大小 所以在这个声明中 字符串[] s=新字符串[100]; 我们不必浪费我们的记忆。

      【讨论】: