.net - 了解 VB.NET P/Invoke 声明中的 VBByRefStr

标签 .net vb.net pinvoke marshalling

当尝试使用在 C# 的 VB.NET 程序集中创建的 P/Invoke 声明时,我注意到 string参数变为 ref string参数。

仔细检查会发现,例如

Public Declare Unicode Function RegDeleteValue Lib "advapi32.dll" Alias "RegDeleteValueW" ( _
ByVal hKey As IntPtr, ByVal lpValueName As String) As UInteger

编译为

[DllImport(...)]public static extern uint RegDeleteValue(
    IntPtr hKey, [MarshalAs(UnmanagedType.VBByRefStr)] ref string lpValueName);

关于 MSDN我阅读:

VBByRefStr: A value that enables Visual Basic .NET to change a string in unmanaged code, and have the results reflected in managed code. This value is supported only for platform invoke. This is default value in Visual Basic for ByVal strings.

我还是不明白。为什么只有string lpValueName在 C# 中(参见 pinvoke.net - edit: for RegDeleteKey 正如 Damien_The_Unbeliever 指出的那样,签名与 RegDeleteValue 相同)但很奇怪 VBByRefStr在 VB.NET 中?我应该用 <MarshalAs(UnmanagedType.LPWStr)> 申报吗?在 VB.NET 中避免 ref在 C# 中?或者这有什么不利影响吗?

最佳答案

这是为了向后兼容 VB6 Declare 语句。

当使用 ByVal x As String 时,您表示要将 VB UTF-16“字符串”类型转换为 ASCII 表示形式,将指向该 ASCII 缓冲区的指针传递给该参数,并在调用成功后将其转换为该缓冲区的内容返回到原始的 UTF-16 字符串。

这随后在 VB.NET 中得到了增强,以支持 Unicode API 调用。但是,我认为 VBByRefStr 常量指示在 .NET 中完成的编码必须完全遵循 VB6 中的方法。

如果您想要 UnmanagedType.LPWStr 的标准编码,请使用属性。

关于.net - 了解 VB.NET P/Invoke 声明中的 VBByRefStr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43385670/

相关文章:

c# - 在 C# 中使用 TaskDialog 时出现 EntryPointNotFoundException

c# - 在 .NET 中收到方法调用通知

.net - 将支持 HTTPS、签名证书和签名用户名 token 的 WCF 自定义绑定(bind)

vb.net - 在 VB 中使用 Excel 数据填充 DataGrid 列

vb.net - 如何清除datagridview中的所有数据且不影响删除数据

c# - 具有未指定长度数组的 PInvoke 结构

c# - 如何在 C# 中编码(marshal) C++ 枚举

c# - 在 C# 中启动 STAThread

c# - C# 中的 InitializeComponent 不存在

c++ - VB.NET 错误 "Value of type ' Ushort' cannot be converted to 'Ushort()' "从 native C++ DLL 读取二维字节数组