为什么C#和VB.NET以不同的方式隐式编组char *?
所以我有一个用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
,为什么不能另一种语言,需要一个完全不同的类?
(为清晰起见编辑了标题)
现在我知道VB.NET和C#是完全不同的,但我想我总是认为字符串是字符串
字符串在.net中是不可变的。 问问自己,为什么ByVal
传递不可变数据类型会导致值发生变化。 对于正常函数,这不会发生,仅适用于Declare
。
我猜这一切都与保持与经典VB6的Declare
语句的向后兼容性有关,这是通过这种方式完成的。 在我看来,这里的黑羊是VB.net代码而不是C#代码。
因为他们是不同的语言。 VB.NET可以解决很多C#无法解决的问题。 老实说,我没有看到问题。
我应该补充一下你可以简单地做一下ref char []并且它会有效。 我看到的一个问题是你的调用约定不匹配。
所以这也可能是你得到内存exception错误的原因。
由于字符串从一开始就是不可变的,我猜测VB以某种方式唤起调用以允许函数修改缓冲区。 也许内部VB实际上也传递了一个StringBuilder。
如果这是VB团队设计调用以使API调用更像VB6,我不会感到惊讶。