DllImport,Char *&和StringBuilder C / C#

时间:2011-05-19 18:47:20

标签: c# dllimport stringbuilder

我有一个问题,我试着查看几乎所有的海报解决方案,找不到合适的解决方案。

问题很简单,想在我的托管C#中使用非托管C代码返回字符串。 c函数是:

extern "C" __declspec(dllexport) int process_batch (char *&result);

在C#中导入了DLL:

[DllImport("mydll.dll")]
public static extern IntPtr process_batch(StringBuilder result);

我运行,但我的StringBuilder中的返回值是一个7-8字符的无意义字符串! (我认为内存地址)

我尝试在StringBuilder之前添加ref,这次我在StringBuilder中获得了正确的返回值,但是我得到了AccessViolationException: 尝试读取或写入受保护的内存。这通常表明其他内存已损坏。

所以我需要你的帮助来解决这个问题。

还有一件事,我在c中使用malloc将内存分配给char *变量。

谢谢,

2 个答案:

答案 0 :(得分:4)

如果你真的想这样做,请将参数作为ref IntPtr传递,然后拨打Marshal.PtrToStringAnsi或类似名称。

[DllImport("mydll.dll")]
public static extern IntPtr process_batch(ref IntPtr result);

请注意,由于您在C中使用malloc分配字符串,因此.NET程序必须跟踪返回的指针,以便它可以将其传递给您以进行解除分配。否则你会有内存泄漏。

如果要传递ref StringBuilder,则无法释放C程序分配的内存。

另外,正如有人在另一篇文章中评论过的那样,你需要设置调用约定:

[DllImport("mydll.dll", CallingConvention=CallingConvention.Cdecl)]

答案 1 :(得分:2)

我一直在成功使用以下代码:

[DllImport("user32.dll", EntryPoint = "GetClassName", ExactSpelling = false,
            CharSet = CharSet.Auto, SetLastError = true)]
private static extern int _GetClassName(IntPtr hwnd, StringBuilder lpClassName,
            int nMaxCount);

public static string GetClassName(IntPtr hWnd)
{
   StringBuilder title = new StringBuilder(MAXTITLE);
   int titleLength = _GetClassName(hWnd, title, title.Capacity + 1);
   title.Length = titleLength;

   return title.ToString();
}

我建议通过DllImportAttribute更具体地声明导入的方法。例如,尝试CharSet = CharSet.Auto

我知道这与您原来的问题并不完全相关,因为这会使用Windows API,但它可能会有所帮助。