处理从c ++ dll返回到C#的数组

时间:2012-04-10 08:35:12

标签: c# c++ marshalling

我在用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???
        }


    }

帮助继续进行。

4 个答案:

答案 0 :(得分:3)

无法处理此类数组。 {C}函数在堆栈中分配char a[2],并在返回时立即销毁。您应该从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);
}

答案 1 :(得分:2)

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

我们的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);
        }
  

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

答案 2 :(得分:1)

答案是

 string stra = Marshal.PtrToStringAnsi(a);

但是你也有问题,dll会根据你的代码返回垃圾,因为char *是一个本地的c样式字符串。 如果你会返回类似的东西,那就没关系了。

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

答案 3 :(得分:-2)

尝试使用非空StringBuilder作为返回值。