【问题标题】:How to convert between a C# String and C Char pointer如何在 C# String 和 C Char 指针之间进行转换
【发布时间】:2016-10-17 15:17:26
【问题描述】:

我有一个用 C 语言编写的大型库,我想在 C# 程序中用作 DLL。大多数 C 代码将由库自己的函数使用,但我确实需要一个函数才能从 C# 项目中调用。

所以下面有一个示例 C 函数

__declspec(dllexport) char* test(char* a){
    char* b = "World";
    char* result = malloc(strlen(a) + strlen(b) + 1);

    strcpy(result, a);
    strcpy(result, b);

    return result;
}

现在在 C# 代码中我得到了using System.Running.InteropServices; 还有[DllImport("mydll.dll")],但我不确定如何声明该函数。

public static extern char* test(char* a); 显然不起作用,因为 C# 不像 C 那样支持指针。

那么我应该如何将一个字符串传递给这个 C 函数并让它也返回一个字符串呢?

【问题讨论】:

  • 你必须使用 C 库吗?为什么你不能编写自己的方法来在 C# 中处理同样的事情?在我看来这似乎很简单..
  • C# 确实支持指针,就像 C 一样,但您在这里不需要它们。您的函数返回 int 但您试图返回 char* - 这是一个错误。通常你为函数提供一个缓冲区来填充,或者你必须导出第二个函数来释放你分配的字符串。
  • 返回这样的字符串是一种泄漏。请参阅stackoverflow.com/questions/5298268/… 了解正确的做法。
  • @MethodMan 这只是一个例子。真正的 C 代码要深入得多。
  • 参数只是字符串。然而,返回值是一个问题,pinvoke marshaller 将尝试使用 CoTaskMemFree() 释放字符串缓冲区,但这是行不通的。请注意,这个函数也很难从 C 程序中可靠地调用。您需要公开另一个调用 free() 的辅助函数。在 C# 中声明为 IntPtr 并使用 Marshal.PtrToStringAnsi()。更智能的签名是 int test(const char* a, char* buffer, int buflen),允许您将第二个参数声明为 StringBuilder,并在 buflen 不够大时返回错误代码。

标签: c# c


【解决方案1】:

您正在寻找 MarshalAs 属性:

   [DllImport("mydll.dll")]
   static public int test([MarshalAs(UnmanagedType.LPStr)]String a);

至于返回动态分配的 C 字符串,这是个坏主意。您将如何可靠地取消分配字符串?这是内存泄漏的秘诀。在 C# 中分配一个字节数组,将其固定并将其连同其大小一起传递给 C 代码,以便 C 代码可以将结果复制到其中。然后使用System.Text.Encoding.ASCII.GetString()转换成字符串。

【讨论】:

  • 是的,除了 OP 的功能已损坏(请参阅我对问题的评论)
猜你喜欢
  • 2016-03-09
  • 2012-12-17
  • 2011-10-27
  • 2018-11-07
  • 2023-03-08
  • 1970-01-01
  • 1970-01-01
  • 2021-03-22
  • 1970-01-01
相关资源
最近更新 更多