在c# COM中处理NULL指针输出参数

本文关键字:指针 输出 参数 NULL 处理 COM | 更新日期: 2023-09-27 18:01:32

我正在使用一个COM插件接口,它具有以下函数定义:

HRESULT foo ( [out, ref] VARIANT* a, [out, ref] VARIANT* b );

当使用tlbimp (tlbimp2.exe from codeplex)时,.NET库有以下接口函数:

int foo ( out object a, out object b );

问题是调用程序将进行函数调用:

VARIANT a;
::InitVariant( &a );
plugin->foo( &a, NULL );
在c#中我实现了这个函数:
int foo ( out object a, out object b )
{
    a = 1;
    b = 2;
    return 0; // S_OK
}

当一切都说了并做了之后,应用程序实际上得到一个E_POINTER返回值,而不是S_OK。我认为这是因为传递了out参数的NULL。

是否有一种方法来检查地址指针是否为NULL在c#实现?

注意:我们的参数没有初始化,所以你根本不能使用参数。

我已经尝试将接口实现为[in, out, ref]来强制c#使用(ref object a, ref object b),但这也不起作用。

Hans是绝对正确的,如果我们声明它为[out,ref],我们应该使用NULL ptr来调用函数。

erurainon也是正确的,我们可以使用IntPtr来获取变量*.

所以这是如何修复的:

int foo ([MarshalAs(UnmanagedType.Struct)]out object a, [MarshalAs(UnmanagedType.Struct)]out object b);

int foo ([MarshalAs(UnmanagedType.Struct)]out object a, IntPtr b );

现在我们可以测试NULL的情况:

if ( b == IntPtr.Zero )

但是,由于我们处理的是Variant,所以不能像这样将值复制到IntPtr中:

Marshal.StructureToPtr( myValue, b, false );

所以在这篇文章之后,你需要创建一个struct类:

[StructLayout(LayoutKind.Explicit, Size = 16)]
public struct PropVariant
{
    [FieldOffset(0)]
    public VarEnum variantType;
    [FieldOffset(8)]
    public IntPtr pointerValue;
    [FieldOffset(8)]
    public byte byteValue;
    [FieldOffset(8)]
    public long longValue;
    [FieldOffset(8)]
    public double dateValue;
    [FieldOffset(8)]
    public short boolValue;
}

最后的函数是这样的:

int foo( out object a, IntPtr b )
{
    a = 100;
    if ( b != IntPtr.Zero )
    {
        var time = new PropVariant();
        time.dateTime = DateTime.Now.ToOADate();
        time.variantType = VarEnum.VT_DATE;
        Marshal.StructureToPtr( time, b, false );
    }
    return 0; // S_OK
}

希望这对将来的人有所帮助

在c# COM中处理NULL指针输出参数

从MIDL文档:

The [ref] attribute identifies a reference pointer. It is used simply to represent a level of indirection
....
A reference pointer has the following characteristics:
 - Always points to valid storage; never has the value NULL. A reference pointer can always be dereferenced.

代码无效,它传递了NULL。直接违反合同。这就是buck停止的地方,您将使用来修复MIDL或本机代码。

汉斯是对的。要么你不允许你的API被NULL参数调用,要么你用IntPtr参数实现你的c#函数,并检查IntPtr.Zero