我正在使用具有以下函数定义的 COM 插件接口:
HRESULT foo ( [out, ref] VARIANT* a, [out, ref] VARIANT* b );
使用 tlbimp(来自 codeplex 的 tlbimp2.exe)时,.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。我认为这是因为 NULL 传递了 out 参数。
有没有办法在 C# 实现中检查地址指针是否为 NULL?
注意:out 参数未初始化,因此您根本无法使用这些参数。
我尝试将接口实现为 [in, out, ref] 以强制 C# 使用( ref object a, ref object b ),但这也不起作用。
更新
Hans 是绝对正确的,如果我们将其声明为 [out,ref],我们应该使用 NULL ptr 调用该函数。
erurainon 也是正确的,我们可以使用 IntPtr 来获取 Variant*。
所以这里是如何修复它:
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 );
因此,在这篇文章之后,您需要创建一个结构类:
[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
}
希望这对将来的其他人有所帮助