首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >DllImport、Char*&和StringBuilder C/C#

DllImport、Char*&和StringBuilder C/C#
EN

Stack Overflow用户
提问于 2011-05-20 02:47:20
回答 2查看 5.3K关注 0票数 4

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

问题很简单,我希望在我的托管C#中有一个非托管C代码的返回字符串。C函数是:

代码语言:javascript
复制
extern "C" __declspec(dllexport) int process_batch (char *&result);

在C#中,我导入了DLL:

代码语言:javascript
复制
[DllImport("mydll.dll")]
public static extern IntPtr process_batch(StringBuilder result);

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

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

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

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

谢谢,

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-05-20 03:22:46

如果您真的想这样做,请将参数作为ref IntPtr传递,然后调用Marshal.PtrToStringAnsi或类似方法。

代码语言:javascript
复制
[DllImport("mydll.dll")]
public static extern IntPtr process_batch(ref IntPtr result);

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

如果你要传递一个ref StringBuilder,你将不能释放由C程序分配的内存。

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

代码语言:javascript
复制
[DllImport("mydll.dll", CallingConvention=CallingConvention.Cdecl)]
票数 4
EN

Stack Overflow用户

发布于 2011-05-20 02:57:53

我已经成功地使用了以下代码:

代码语言:javascript
复制
[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,但它可能会有所帮助。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6063428

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档