2017-04-13 77 views
2

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

仔细检查发现,例如, “VBByRefStr:使Visual Basic .NET中改变非托管代码串,并有结果反映在托管代码中的值

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。此值仅支持平台调用,这是Visual Basic中ByVal字符串的默认值。“

我还是不明白。为什么在C#中只有string lpValueName(参见pinvoke.net- 编辑:对于​​作为Damien_The_Unbeliever指出,签名与RegDeleteValue相同),但在VB.NET中有奇怪的VBByRefStr?我应该在VB.NET中使用<MarshalAs(UnmanagedType.LPWStr)>来声明C#中的ref吗?或者是否有任何不利影响?

+0

不是说它有很大的不同,但你的pinvoke链接是* *不同*功能。 'RegDeleteKey'!='RegDeleteValue'。我无法在advapi32中找到['RegDeleteValue'](https://msdn.microsoft.com/en-us/library/windows/desktop/ms724851(v = vs.85).aspx)的PInvoke页面 –

+0

My不好,当我没有找到'RegDeleteValue'时,看起来像是在''RegDeleteKey''结尾。对困惑感到抱歉。但是,主要的观察结果也与'RegDeleteKey'一样:-) –

回答

3

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

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

随后在VB.NET中对此进行了增强以支持Unicode API调用。但是,我会想象VBByRefStr常量表示.NET中的编组必须完全遵循VB6中的方法。

如果您想要UnmanagedType.LPWStr的标准编组,然后使用属性。

+0

有道理,谢谢解释!我想我应该整体摆脱VB6风格的'Declare'语句,并使用'DllImport'来代替 –