如何将void指针(又名。void*
或句柄)放入COM VARIANT
- Type中。包装类_variant_t
将其错误地转换为布尔值。但是我需要将它作为指针放入,以便.NET的COM-Marshaller将其识别为IntPtr
。
我读过的其中一个主题是this one at MSDN Social。他们提出了这样的解决方案:
VARIANTARG Arg;
VariantInit(&Arg);
V_VT(&Arg) = VT_INT;
V_INT(&Arg) = (int)m_hWnd;
此解决方案的问题是,V_INT
(成员intVal
)是32 bit integer并强制指针为32位指针。换句话说:我无法传输64位指针。该问题是否有任何解决方案?还有其他任何方式将其转换为64位整数吗?
我已经通过一些代码对此进行了测试。因此,我使用.NET方法接收任何System.Object
并输出其值和类型。
public static void TakePtr(object ptr)
{
Console.WriteLine("Received a " + ptr.GetType() + " with value " + ptr);
}
我的VARIANT
已填充v.llVal = 0; v.byref = myPointer;
的兼容性,因此应始终正确编译32/64位指针。
此外,我需要设置变体类型,以便.NET将其映射到System.IntPtr
而不进行。 (因为对于真正的程序集,我无法更改代码,也不想包装它。这会增加主要的复杂性。)
System.IntPtr
向后转移为VT_INT
,将mapp转发为System.Int32
。VT_I8
mapps System.Int64
但不是System.IntPtr
。那么VARENUM
标志会指定System.IntPtr
?
答案 0 :(得分:5)
这是不可能的,VARIANT是一种自动化类型。自动化不喜欢处理未知类型的指针,没有安全的方法来取消引用它们。支持的唯一指针类型是IUnknown *和IDispatch *,接口指针。
充其量你可以将它存储为VT_I8,它可以长时间编组。然后您可以将其转换为IntPtr。
答案 1 :(得分:2)
目前我找到了一个解决完整问题的临时解决方案:要在调用方法时显式定义参数类型,我将使用另一种调用机制。因此,我使用以下方法,它几乎包装类型invoke方法的参数,但另外检查类型并相应地转换它们,以便System.IntPtr
被识别为这样,而不是System.Int32
或{ {1}}。
System.Int64
此方法的调用可能如下所示:
public static object InvokeMember(this Type type, object obj, String name, System.Reflection.BindingFlags invokeAttr, Type[] argTypes, object[] argValues)
{
if (argTypes.Length != argValues.Length) throw new InvalidOperationException("Mismatching count of types an parameters.");
for (int i = 0; i < argTypes.Length; i++) if (argTypes[i] == typeof(IntPtr)) argValues[i] = new IntPtr(Convert.ToInt64(argValues[i]));
return type.InvokeMember(name, invokeAttr, null, obj, argValues);
}
最后必须从COM中使用它来传递指针VARIANTs,它们按照描述填充:typeof(ExampleLib.HelloNET).InvokeMember(
null,
"TakePtr",
BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod,
new Type[] { typeof(IntPtr) },
new object[] { 42 });
/已解决: - )
答案 2 :(得分:1)
变种的PVOID byref;
成员看起来很有帮助。但我不确定应该设置哪种类型。
你可以像Hans建议的那样使用LONGLONG llVal
,因为即使是32位平台也有IntPtr(Int64)
构造函数。应该工作,直到有人发明128位指针。
答案 3 :(得分:0)
我有类似的问题。将64位指针放入PVOID变体类型时, 它被截断/编组为32位指针! 所以我然后使用VT_I8变体类型并将指针放入其llVal成员中,一切都运行良好。
答案 4 :(得分:0)
我使用VT_VOID和byref param几乎没有任何问题。几乎是因为在某些情况下,.NET引发了关于从本机到托管对象的错误转换的MDA错误(InvalidVariant错误)
我无法检查问题是否是byref是0,因为它总是不会出现。 :)