【问题标题】:How do I pass a const char* to a C function from C#?如何从 C# 将 const char* 传递给 C 函数?
【发布时间】:2015-05-04 11:08:00
【问题描述】:

我尝试从我的 C# 应用程序中的外部 DLL 调用普通 C 函数。这个函数定义为

void set_param(const char *data)

现在我在使用这个函数时遇到了一些问题:

  1. 如何在 C# 代码中指定这个“const”? public static extern void set_param(sbyte *data) 似乎错过了“const”部分。

  2. 在调用此函数时,如何交出一个普通的 8 位 C 字符串?对 set_param("127.0.0.1") 的调用会导致错误消息,“无法从 'string' 转换为 'sbyte'”*。

【问题讨论】:

  • 我认为public static extern void set_param(string data) 应该可以工作。
  • 我想你会在这里找到很多例子pinvoke.net

标签: c# .net dll pinvoke marshalling


【解决方案1】:

看起来您将使用 ANSI 字符集,因此您可以像这样声明 P/Invoke:

[DllImport("yourdll.dll", CharSet = CharSet.Ansi)]
public static extern void set_param([MarshalAs(UnmanagedType.LPStr)] string lpString);

.NET marshaller 处理复制字符串并将数据转换为适合您的类型。

如果您遇到堆栈不平衡的错误,则需要设置调用约定以匹配您的 C DLL,例如:

[DllImport("yourdll.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]

有关使用 Windows API 函数的大量示例,请参阅 pinvoke.net

另见Microsoft's documentation on pinvoking strings

【讨论】:

  • 这会导致异常:对 PInvoke 函数 'yourdll.dll::set_param' 的调用使堆栈不平衡。这可能是因为托管 PInvoke 签名与非托管目标签名不匹配。
  • @Elmi 所以你需要知道 C DLL 的调用约定,这样你才能在 P/Invoke 中指定它。它使用什么调用约定?
  • Matthew Watson:该 DLL 具有普通未修饰的 C 函数,全部为 ANSI-C,__declspec(dllexport)
  • @Elmi 因此我认为您想要CallingConvention = CallingConvention.Cdecl,但如果这不起作用,请尝试其他的。
【解决方案2】:

const char* 只是 .NET 中的 string - 托管方(还)不理解只读参数的概念。

如果您在 P/Invoke 上下文中使用它,您应该声明一个 MarshalAs 属性并将其编组为 LPStr。生成的签名看起来类似于

[DllImport("SomeModule.dll")]
public static extern void set_param([MarshalAs(UnmanagedType.LPStr)]string lpString);

还有article on MSDN 提供有关如何将本机字符串编组到托管环境的更多信息。

【讨论】:

  • .NET Unicode 中不是字符串吗?即使使用 UTF-8 编码,它如何可靠地处理 ASCII 128-255(特定于语言环境等)?
  • @PeterMortensen 对于 ASCII 128-255,您将使用 LPWStr,它表示一个 2 字节的字符字符串。从 .NET 4.7 开始,LPUTF8Str 被添加到“本机”支持 UTF8 字符串,而不是返回 IntPtr 并手动处理它们。附带说明一下,.NET 中的字符串是 UTF-16,这就是微软所说的 Unicode,但它是 Unicode iirc 的不同风格,但你说 .NET 中的字符串是 Unicode 是正确的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-20
  • 2013-12-19
  • 2011-05-22
  • 2012-07-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多