简体   繁体   English

DllImport,Char *&和StringBuilder C / C#

[英]DllImport, Char*& and StringBuilder C/C#

I have a problem, I tried to look at almost all the poster solutions, unsuccessful to find a suitable one. 我有一个问题,我试着看几乎所有的海报解决方案,找不到合适的解决方案。

The question is easy, Want to have a return string from unmanaged C code in my managed C#. 问题很简单,想在我的托管C#中使用非托管C代码返回一个字符串。 The c function is: c函数是:

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

and in C# I imported the DLL: 在C#中我导入了DLL:

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

I run, but the return value in my StringBuilder is a 7-8 character string of non-sense! 我跑,但我的StringBuilder中的返回值是一个7-8字符的无意义字符串! (I think the memory address) (我认为内存地址)

I tried adding ref before the StringBuilder, this time I get the correct return value in StringBuilder but I get AccessViolationException : Attempted to read or write protected memory. 我尝试在StringBuilder之前添加ref,这次我在StringBuilder中获得了正确的返回值但是我得到了AccessViolationException:尝试读取或写入受保护的内存。 This is often an indication that other memory is corrupt. 这通常表明其他内存已损坏。

So I need your help to fix this. 所以我需要你的帮助来解决这个问题。

Just one more thing, I use malloc in c for allocating the memory to the char* variable. 还有一件事,我在c中使用malloc将内存分配给char *变量。

Thanks, 谢谢,

If you really want to do that, pass the parameter as a ref IntPtr , then call Marshal.PtrToStringAnsi , or similar. 如果你真的想这样做,将参数作为ref IntPtr传递,然后调用Marshal.PtrToStringAnsi或类似的。

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

Note that, since you're allocating the string with malloc in C, the .NET program will have to keep track of the returned pointer so that it can pass it back to you to be deallocated. 请注意,由于您在C中使用malloc分配字符串,因此.NET程序必须跟踪返回的指针,以便它可以将其传递给您以进行解除分配。 Otherwise you'll have a memory leak. 否则你会有内存泄漏。

If you were to pass a ref StringBuilder , you wouldn't be able to deallocate the memory that was allocated by the C program. 如果您要传递ref StringBuilder ,则无法释放C程序分配的内存。

Also, as somebody commented in another post, you need to set the calling convention: 另外,正如有人在另一篇文章中评论过的那样,你需要设置调用约定:

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

I've been using the following code successfully: 我一直在成功使用以下代码:

[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();
}

I'd advise for a more specific declaration of the imported method via the DllImportAttribute . 我建议通过DllImportAttribute更具体地声明导入的方法。 Try the CharSet = CharSet.Auto bit for instance 例如,尝试CharSet = CharSet.Auto

I know that this is not exactly related to your original problem as this makes use of the Windows API, but maybe it is of help nonetheless. 我知道这与您的原始问题并不完全相关,因为这会使用Windows API,但它可能仍有帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM