【问题标题】:Why do C# and VB.NET implicitly marshal char* differently?为什么 C# 和 VB.NET 以不同方式隐式封送 char*?
【发布时间】:2023-03-22 05:35:01
【问题描述】:

所以我有一个用 C++ 编写的函数,看起来像这样......

extern "C" __declspec(dllexport) int __stdcall SomeFunction(char *theData)
{
    // stuff
}

...我正在我当前的项目中使用它(用 C# 编写)。还有其他项目使用这个函数用VB写的,看起来像这样:

Public Declare Function SomeFunction Lib "MyDLL.dll" _
    Alias "_SomeFunction@4" (ByVal theData As String) As Integer

所以我尝试在 C# 中编写一个等价物,但发现使用字符串类型实际上对我不起作用 - 字符串会返回与我传递给它的数据相同的数据。我尝试使用 "ref string" 来通过引用传递字符串,但我遇到了内存访问冲突。

经过一番挖掘,我发现这是在 C# 中的正确实现:

[DllImport("MyDLL.dll", EntryPoint = "_SomeFunction@4")]
public static extern int SomeFunction(StringBuilder theData);

现在我知道 VB.NET 和 C# 完全不同,但我想我一直认为字符串是字符串。如果一种语言可以将char* 隐式编组为String,为什么另一种语言不能,完全需要不同的类?

(为了清楚起见,编辑了标题)

【问题讨论】:

  • 用 JustDecompile 或 .NET Reflector 看看这两个版本可能会很有趣。

标签: c# c++ vb.net string marshalling


【解决方案1】:

因为它们是不同的语言。 VB.NET 可以做很多 C# 做不到的事情,原因有很多。老实说,我没有看到问题。

我应该补充一点,您可以简单地执行 ref char[] 并且它会起作用。我看到的一个问题是您的调用约定不匹配。

所以这也可能是您遇到内存异常错误的原因。

【讨论】:

  • 调用约定很好,stdcall 在上面的所有代码中。 AV 是因为 ref string 根本不匹配 char*。为此,必须在 C# 中使用 StringBuilder。本机代码无法构造有效的 .net String 对象。
【解决方案2】:

现在我知道 VB.NET 和 C# 完全不同,但我想我一直认为字符串是字符串

.net 中的字符串为 immutable。问问自己为什么ByVal 传递不可变数据类型会导致值发生变化。正常功能不会发生这种情况,仅适用于Declare

我猜这一切都与保持与经典 VB6 中以这种方式完成的 Declare 语句的一些向后兼容性有关。在我看来,这里的害群之马是 VB.net 代码而不是 C# 代码。

【讨论】:

  • 另外,只有Declare 这样做。 <DllImport()> 没有(VB 确实使用 ByRef 参数做了一些有趣的事情,以允许您传入属性和常量,但这不是其中之一)
  • +1。这绝对是为了向后兼容 VB6 Declare 语句。在新的 VB.Net 代码中,您可能更喜欢 <DllImport()>。在他们的智慧中,VB6 设计者决定 VB6 中的 ByVal As String Declare 将等同于 C char *。在幕后,VB6 运行时根据当前的 Windows 代码页以“ANSI”格式创建原始 Unicode 字符串的副本,并将副本的地址传递给 DLL。为了完整起见,这里是the original Microsoft VB6 documentation 将 DLL 与 VB6 集成。
【解决方案3】:

由于字符串一开始是不可变的,我猜测 VB 会以某种方式引导调用以允许函数修改缓冲区。也许 VB 在内部实际上也传递了一个 StringBuilder。

如果这是 VB 团队的设计调用,使 API 调用更像 VB6,我不会感到惊讶。

【讨论】:

    猜你喜欢
    • 2013-10-05
    • 2013-03-20
    • 1970-01-01
    • 1970-01-01
    • 2010-12-01
    • 2018-09-26
    • 1970-01-01
    • 1970-01-01
    • 2021-06-01
    相关资源
    最近更新 更多