为什么 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
,为什么另一种语言不能,需要完全不同的类?
(为了清晰起见编辑了标题)
So I have a function, written in C++, that looks like this...
extern "C" __declspec(dllexport) int __stdcall SomeFunction(char *theData)
{
// stuff
}
... and I'm using it in my current project (written in C#). There are other projects that use this function written in VB, looking like this:
Public Declare Function SomeFunction Lib "MyDLL.dll" _
Alias "_SomeFunction@4" (ByVal theData As String) As Integer
So I tried writing an equivalent in C#, but found that using the string type didn't actually work for me - the string would come back with the same data I passed it in with. I tried using "ref string"
instead to pass the string by reference and I got a memory access violation.
After doing some digging, I found that this was the correct implementation in C#:
[DllImport("MyDLL.dll", EntryPoint = "_SomeFunction@4")]
public static extern int SomeFunction(StringBuilder theData);
Now I know that VB.NET and C# are quite different, but I suppose I always assumed that strings were strings. If one language can marshal char*
to String
implicitly, why can't the other, requiring a different class altogether?
(edited the title for clarity)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
字符串是 .net 中不可变。问问自己为什么
ByVal
传递不可变数据类型会导致值发生变化。对于普通函数来说,这种情况不会发生,只有Declare
才会发生这种情况。我猜这一切都与保持与经典 VB6 中的
Declare
语句的向后兼容性有关,这些语句是通过这种方式完成的。在我看来,这里的害群之马是 VB.net 代码而不是 C# 代码。Strings are immutable in .net. Ask yourself why it is that
ByVal
passing of an immutable data type can result in the value changing. That doesn't happen for normal functions, just forDeclare
.I'd guess it all has to do with maintaining some backwards compatibility with
Declare
statements from classic VB6 which were done this way. To my mind the black sheep here is the VB.net code rather than the C# code.因为它们是不同的语言。 VB.NET 可以完成很多 C# 由于多种原因而无法完成的事情。老实说,我不认为有什么问题。
我应该补充一点,您可以简单地执行 ref char[] ,它就会起作用。我发现的一个问题是您的调用约定不匹配。
因此,这也可能是您出现内存异常错误的原因。
Because they are different languages. VB.NET can a great deal of things that C# cannot for many reasons. I don't see the problem to be honest.
I should add you could have simply did ref char[] and it would have worked. One problem I see is that your calling conventions do not match.
So that also is likely the reason you got a memory exception error.
由于字符串一开始就是不可变的,我猜测 VB 以某种方式引导调用以允许函数修改缓冲区。也许VB内部实际上也在传递一个StringBuilder。
如果这是 VB 团队的设计调用,旨在使 API 调用更像 VB6,我不会感到惊讶。
Since string is immutable to begin with, I'm guessing that VB somehow wizards the call to allow for the buffer to be modified by the function. Perhaps internally VB is actually passing a StringBuilder as well.
I wouldn't be surprised if this was a design call by the VB team to make API calls more VB6-like.