为什么c#和VB.NET隐式地以不同的方式封送char*

本文关键字:方式封 char VB NET 为什么 | 更新日期: 2023-09-27 18:11:17

我有一个用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,为什么另一种语言不能,需要完全不同的类?

(为清晰起见编辑了标题)

为什么c#和VB.NET隐式地以不同的方式封送char*

现在我知道了VB。NET和c#有很大的不同,但我想我一直认为字符串就是字符串

字符串在。net中是不可变的。问问自己,为什么传递不可变数据类型的ByVal会导致值改变。这不会发生在正常的函数中,只发生在Declare中。

我猜这一切都与维护一些向后兼容性从经典VB6 Declare语句是这样做的。在我看来,害群之马是VB.net代码,而不是c#代码。

因为是不同的语言。VB。NET可以做很多c#由于很多原因不能做的事情。老实说,我看不出有什么问题。

我应该补充一下,你可以简单地使用ref char[],它就可以工作了。我看到的一个问题是你的调用约定不匹配。

所以这也可能是你得到内存异常错误的原因

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

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