C++ 问题:需要在运行时使用传递指针的反射作为参数进行COM互操作吗?

C++ 问题:需要在运行时使用传递指针的反射作为参数进行COM互操作吗?,c++,reflection,dynamic,.net-4.0,com-interop,C++,Reflection,Dynamic,.net 4.0,Com Interop,我需要在运行时使用反射生成COM IntetrOp。我的本机COM对象的公开方法有一些参数,如指针DWORD*和一些双指针DWORD**以及一些用户定义的typese.g SomeUDTType objSmeUDTType,反之亦然。SomeUDTType*pSomeUDTType 现在,对于动态方法调用,我们有一个选项可以将参数作为对象数组传递,即object[],并静态填充该数组 但我需要传递指针、引用和指向指针的指针。目前,我如何能够将对象数组填充为简单数据类型、指针或引用以及指向指针的指

我需要在运行时使用反射生成COM IntetrOp。我的本机COM对象的公开方法有一些参数,如指针DWORD*和一些双指针DWORD**以及一些用户定义的typese.g SomeUDTType objSmeUDTType,反之亦然。SomeUDTType*pSomeUDTType

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

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

工作示例:

本机COM公开方法:

由tlbimp.exe COMInterop翻译

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

请看这里:

       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包装器?如果在哪种情况下? 当做 Usman只需将参数的值直接放入数组中即可。对于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);

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

我严重怀疑您是否能够做到这一点。此COM服务器似乎没有使用与自动化兼容的参数类型。这些指针实际上看起来像数组。首先让它与互操作库一起工作。如果这不起作用,那么您必须为它编写一个C++/CLI包装器。这些只是简单的指针。指向BSTR和一些DWORD的指针。BSTR指针只指向BSTR,DWORD有一些DWORD地址。这里的问题不在于它们是数组还是简单指针,问题在于在将数据映射到相应的BSTR指针和DWORD指针时,使用InterOp对方法进行相应的调用,因为在正常情况下它的调用是预期的。。我正在使用互操作库。此处使用tlbimp.exe将其转换为托管.NET对象,然后对其应用反射。这是一个RCWRuntime可调用包装器,它将调用传输到本机COM世界。这是一个好问题:您是否尝试在没有反射的情况下调用您的COM API,即通过代码中对MyCallableMethod的普通调用?它起作用了吗?如果没有,你应该先把精力放在完成工作上,然后再进行反思。。。。。对ref.没有问题。。我声明了普通uint,并将其作为ref传递。它会生成运行时异常:“System.Int32”类型的对象无法转换为“System.UInt32&”类型。这是因为它需要一个uint,而您给了它一个int。如果您使用的是文本,例如123,那么就用u:123u作为后缀。如果您使用了某个计算值,那么显式地将其转换为uint。您能告诉我如何传递用户定义类型的指针和引用吗?例如,在上述情况下,SomeUDT*pSomeUDT。?在.NET中,一切都是引用。但当我把oCustomType放在其中一个参数中,即放在参数[3]中时。它生成运行时异常:目标调用方法未处理:调用的目标引发了异常。事实上,没有什么比这更重要的了——CLR引用不是一流的,不能作为值放入数组中。您可以得到的最好的方法是我描述的方法,在这种方法中,您输入装箱的值,然后反射将对每个框的引用传递给实际代码。指针在这里不相关,因为您的方法声明没有任何指针,引用和指针是不同的类型。至于您的异常,它只是指示方法本身在调用后抛出异常。要找出它抛出的实际异常,您必须查看所获得的TargetInvocationException的InnerException属性。请发布你从那里得到的消息,以及给你更新问题的代码,我们将从那里开始。
       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);   
 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);