English 中文(简体)
如何将void*放入COM VARIANT中,以便COM Interop将其封送为IntPtr。网?
原标题:How do I put a void* into a COM VARIANT so that it gets marshalled as IntPtr by COM-Interop to .NET?

如何将空指针(又名void*或句柄)放入COM变量-类型。包装器类_variant_t将其错误地转换为布尔值。但我需要将其作为指针放入,以便.NET的COM Marshaller将其识别为IntPtr

我读过的一个帖子是这是MSDN Social上的一个。他们建议了这样的解决方案:

VARIANTARG Arg; 
VariantInit(&Arg);
V_VT(&Arg) = VT_INT;
V_INT(&Arg) = (int)m_hWnd; 

此解决方案的问题是,V_INT(成员intVal32位整数,并强制指针为32位指针。换句话说:我无法传输64位指针。这个问题有什么解决方案吗?还有其他方法可以将其作为64位整数传输吗?

我已经用一些代码测试过了。因此,我使用a。NET方法接收任何系统。对象,并输出其值和类型。

public static void TakePtr(object ptr)
{
    Console.WriteLine("Received a " + ptr.GetType() + " with value " + ptr);
}

My VARIANT is filled for compatibility by v.llVal = 0; v.byref = myPointer; so it should get compiled always correctly regarding 32/64 bit pointers. Furthermore I need to set the variant type so that .NET mapps it to System.IntPtr without casting. (Because for the real Assembly I can t change the code and don t want to wrapp it. That would add major complexity.).

  • .NET transfers a System.IntPtr backwards as VT_INT, which forewards mapps to System.Int32.
  • VT_I8 mapps to System.Int64 but not System.IntPtr.

因此,什么VARENUM标志将指定一个系统。IntPtr

最佳回答

目前,我找到了一个临时解决方案来解决整个问题:为了在调用方法时明确定义参数类型,我将使用另一种调用机制。因此,我使用以下方法,它几乎封装了类型invoke方法的参数,但额外检查了类型并相应地转换了它们,从而形成了一个系统。IntPtr被识别为这样的系统,而不是系统。Int32系统。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);
}

调用此方法可能如下:

typeof(ExampleLib.HelloNET).InvokeMember(
    null,
    "TakePtr",
    BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod,
    new Type[] { typeof(IntPtr) },
    new object[] { 42 });

最后,必须从COM使用它来传递指针VARIANTs,其填充方式如下:v.llVal=0;v.byref=myPointer;v.vt=vt_INT

/已解决:-)

问题回答

这是不可能的,VARIANT是一种自动化类型。自动化不喜欢处理指向未知类型的指针,没有安全的方法来解除对它们的引用。唯一受支持的指针类型是接口指针,即Json*和IDispatch*。

充其量,您可以将其存储为VT_I8,它将编组为long。然后,您可以将其转换为IntPtr。

PVOID byref变量成员看起来很有帮助。但我不确定应该设置哪种类型来搭配它。

您可以按照Hans的建议使用LONGLONG llVal,因为即使是32位平台也有IntPtr(Int64)constructor。应该工作到有人发明128位指针为止。

I had a similar problem. When a 64 bit pointer is put into a PVOID variant type, it gets truncated/marshalled as a 32 bit pointer! So I then used the VT_I8 variant type and put the pointer into its llVal member and everything worked great.

我使用VT_VOID和byref-param几乎没有任何问题。几乎是因为在某些情况下。NET引发了关于从本机对象到托管对象的错误转换的MDA错误(InvalidVariant错误)

我还无法检查问题是否是byref为0时出现的,因为它并不总是出现。:)





相关问题
Manually implementing high performance algorithms in .NET

As a learning experience I recently tried implementing Quicksort with 3 way partitioning in C#. Apart from needing to add an extra range check on the left/right variables before the recursive call, ...

Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

How do I compare two decimals to 10 decimal places?

I m using decimal type (.net), and I want to see if two numbers are equal. But I only want to be accurate to 10 decimal places. For example take these three numbers. I want them all to be equal. 0....

Exception practices when creating a SynchronizationContext?

I m creating an STA version of the SynchronizationContext for use in Windows Workflow 4.0. I m wondering what to do about exceptions when Post-ing callbacks. The SynchronizationContext can be used ...

Show running instance in single instance application

I am building an application with C#. I managed to turn this into a single instance application by checking if the same process is already running. Process[] pname = Process.GetProcessesByName("...

How to combine DataTrigger and EventTrigger?

NOTE I have asked the related question (with an accepted answer): How to combine DataTrigger and Trigger? I think I need to combine an EventTrigger and a DataTrigger to achieve what I m after: when ...