在托管原型中bool与BOOLEAN

时间:2009-09-15 23:58:05

标签: c# .net interop

我正在尝试使用[CreateSymbolicLink][1] API函数在C#中创建托管原型。 WinBase.h中的原型是:

BOOLEAN APIENTRY CreateSymbolicLink (
    __in LPCWSTR lpSymlinkFileName,
    __in LPCWSTR lpTargetFileName,
    __in DWORD dwFlags
    );

BOOLEAN在WinNT.h中被定义为BYTE。精细。所以我的托管原型应该是:

[DllImport("kernel32.dll", SetLastError = true)]
static extern bool CreateSymbolicLink(string SymlinkFileName, string TargetFileName, UInt32 Flags);

至少,我会这么认为。 bool只是System.Boolean的别名,是一个字节的值。但它似乎没有用。

我执行此代码:

bool retval = CreateSymbolicLink(LinkFilename, TargetFilename, 0);

返回true。但是没有创建符号链接。它没有被创建的原因是我没有使用提升的权限运行。 GetLastError返回1314,根据WinError.h,这意味着我没有所需的权限。正如所料。但为什么我的返回值为true

奇怪的是,如果我将托管原型更改为:

static extern byte CreateSymbolicLink(string SymlinkFileName, string TargetFileName, UInt32 Flags);

和我的代码:

byte retval = CreateSymbolicLink(LinkFilename, TargetFilename, 0);

然后我得到了预期的结果:retval包含0,表示函数失败。

我想我的更大问题是为什么bool不适用于BOOLEAN返回值?

2 个答案:

答案 0 :(得分:4)

使用适当的MarshalAs属性标记返回值:

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.U1)]
static extern bool CreateSymbolicLink(string SymlinkFileName, 
    string TargetFileName, UInt32 Flags);

bool从本机代码到托管代码的默认编组是4个字节 - 您可能会为原始bool返回true,因为其中一个错误编组的堆栈字节非零。 (我猜测最后一部分。)

答案 1 :(得分:1)

由于本机和托管bool之间的差异,具有布尔类型的PInvoke可能会产生意外结果。我写了一篇关于这个主题的博客文章,详细说明了编组各种类型的差异和正确的方法

在这种情况下,Ben M有正确的答案。