【问题标题】:Problem : Need to make COM InterOp at runtime using reflections Passing Pointers as parameters?问题:需要在运行时使用反射传递指针作为参数来制作 COM InterOp?
【发布时间】:2011-04-08 09:29:08
【问题描述】:

我需要在运行时使用反射来制作 COM IntetrOp。我的本机 COM 对象的公开方法有一些参数作为指针 (DWORD*) 和一些双指针 (DWORD**),还有一些是用户定义的类型(例如 SomeUDTType objSmeUDTType),反之亦然它的指针(即 SomeUDTType *pSomeUDTType)。

现在对于动态方法调用,我们有一个选项可以将参数作为对象数组传递,即 object[] 并静态填充该数组。

但我需要传递指针和引用以及指向指针的指针。现在我如何能够将对象数组填充为简单数据类型、指针或引用以及指向指针的指针的混合数据。

工作示例:

本机 COM 公开方法:

STDMETHODIMP MyCallableMethod(DWORD *value_1,BSTR *bstrName,WESContext **a_wesContext)

由 tlbimp.exe (COMInterop) 翻译

UDTINIDLLib.IRuntimeCalling.MyCallableMethod(ref uint, ref string, System.IntPtr)

现在在运行时使用反射在运行时调用这些方法,

看这里:

       Assembly asembly = Assembly.LoadFrom("E:\\UDTInIDL\\Debug\\UDTINIDLLib.dll");
        Type[] types = asembly.GetTypes();


        Type type = null;
        //foreach (Type oType in types)
        {
            try
            {
                type = asembly.GetType("UDTINIDLLib.RuntimeCallingClass");

            }
            catch (TypeLoadException e)
            {
                Console.WriteLine(e.Message);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }

            object parameters = new object[3];

            Type CustomType = asembly.GetType("UDTINIDLLib.WESContext");
            object oCustomType = Activator.CreateInstance(CustomType);
            FieldInfo fieldInfo = CustomType.GetField("MachineName",          BindingFlags.Public | BindingFlags.Instance);

            string MachineName = "ss01-cpu-102";
            string MachineIp = "127.0.0.1";
            string Certificate = "UK/78T";

            fieldInfo.SetValue(oCustomType, MachineName);
            fieldInfo.SetValue(oCustomType, MachineIp);
            fieldInfo.SetValue(oCustomType, Certificate);


            object obj = Activator.CreateInstance(type);
            MethodInfo mInfo = type.GetMethod("MyCallableMethod");
            int lengthOfParams = mInfo.GetParameters().Length;
            ParameterInfo [] oParamInfos = mInfo.GetParameters();



           object[] a_params = new object[lengthOfParams];

            int ValueType = 0;

            for(int iCount = 0; iCount<lengthOfParams; iCount++)
            {
                a_params[iCount] = ???; //Now here this array should be populated with corresponding pointers and other objects (i.e WESContext's obj)
            }

            mInfo.Invoke(obj,  a_params);   

希望代码能够澄清......如果有任何混淆,请告诉我,我会相应地编辑我的问题。

我被困在这里,如果你能帮助我,我将不胜感激。(我对“动态”关键字感到困惑,希望它能解决问题)

是否需要生成 C++/CLI 包装器?如果在什么情况下? 问候 乌斯曼

【问题讨论】:

  • 我严重怀疑你能否完成这项工作。此 COM 服务器似乎没有使用与自动化兼容的参数类型。这些指针实际上看起来像数组。首先让它与互操作库一起工作。如果这不起作用,那么您将不得不为它编写一个 C++/CLI 包装器。
  • 这些只是简单的指针。指向 BSTRS 和一些 DWORD 的指针。 BSTR 指针仅指向 BSTR,而 DWORDS 有一些 DWORDS 地址。问题不在这里,无论它们是数组还是简单的指针,问题是在将数据映射到相应的 BSTR 指针和 DWORD 指针的同时使用 InterOp 对方法进行相应的调用,因为在正常情况下它的调用是预期的。我正在使用 Interop 库。此处使用 tlbimp.exe 将其转换为托管 .NET 对象,然后对其应用反射。这是 RCW(运行时可调用包装器),它将调用转移到本机 COM 世界。
  • 这是一个很好的问题:您是否尝试过在 没有 反射的情况下调用您的 COM API(即通过在代码中对 MyCallableMethod 的简单调用)?它奏效了吗?如果没有,您应该首先专注于完成这项工作,然后将反射留到以后。
  • 它在普通调用中工作正常.....对于 ref 没问题..我声明了普通的 uint 并作为 ref 传递它可以工作..

标签: c++ reflection dynamic .net-4.0 com-interop


【解决方案1】:

只需将参数的 直接放入数组即可。对于out/ref参数,数组的对应元素将被函数返回的新值替换。

对于双指针,到目前为止最简单的方法是使用/unsafe 和非托管指针,就像这样(假设方法使用参数返回值):

 WESContext* pWesContext; // the returned pointer will end up here
 IntPtr ppWesContext = (IntPtr)&pWesContext;

 // direct call
 MyCallableMethod(..., ppWesContext);

 // reflection
 a_params[3] = ppWesContext;
 mInfo.Invoke(obj, a_params);

pWesContext 中获得指向struct 的指针后,您可以使用-&gt; 访问C# 中的成员。不过,我不确定您的 API 的内存管理规则是什么;最终,您可能需要释放该结构,但您尝试调用的 API 文档应描述具体如何执行此操作。

【讨论】:

  • 它会产生运行时异常:'System.Int32' 类型的对象无法转换为'System.UInt32&' 类型。
  • 那是因为它需要一个uint,而你给了它一个int。如果您使用了文字(例如 123),则使用“u”作为后缀:123u。如果您使用了某个计算的值,则将其显式转换为 uint
  • 你能告诉我如何传递用户定义类型的指针和引用,例如在上述情况下 SomeUDT* pSomeUDT.?在 .NET 中,一切都是参考。但是当我将 oCustomType 放入其中一个参数时,即在 params[3] 中。它生成运行时异常:Target Invocation Method was unhandeled : Exception has been throwed by the target of an invocation.
  • 我已经解释了如何在反射中处理引用。它真的没有更多的东西——CLR 引用不是一流的,不能作为值放入数组中。你能得到的最好的方法是我描述的方法,你把装箱的值放进去,然后反射将每个盒子的引用传递给实际的代码。指针在这里不相关,因为您的方法声明没有任何指针(并且 refs 和指针是不同的类型)。
  • 至于你的异常,它只是表明方法本身一旦被调用就抛出了异常。要找出它抛出的实际异常,您必须查看您拥有的TargetInvocationExceptionInnerException 属性。请发布您从那里收到的消息,以及提供给您的代码(只需更新问题),我们将从那里开始。
猜你喜欢
  • 2019-05-11
  • 1970-01-01
  • 2021-01-22
  • 2012-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-28
  • 2018-05-14
相关资源
最近更新 更多