我有一个问题,我试着查看几乎所有的海报解决方案,找不到合适的解决方案。
问题很简单,想在我的托管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 *变量。
谢谢,
答案 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,但它可能会有所帮助。