问题:需要在运行时使用反射传递指针作为参数来进行 COM InterOp?

发布于 2024-09-17 05:11:13 字数 2662 浏览 2 评论 0原文

我需要在运行时使用反射来制作 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);   

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

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

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

I need to make COM IntetrOp at runtime using reflections. My native COM Object's exposed methods have some parameters as pointers (DWORD*) and some double pointers (DWORD**) and some are user defined types(e.g SomeUDTType objSmeUDTType) and vice versa its pointer(i.e. SomeUDTType *pSomeUDTType).

Now for dynamic method invocation, we have single option for passing parameters as array of object i.e object[] and filling this array statically.

But I need to pass pointers and references and pointers to pointers. For now how can I be able to populate object array as mixed data of simple data types, pointers or references and pointers to pointers.

Working Example:

Native COM exposed method :

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

Translated by tlbimp.exe (COMInterop)

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

Now calling these methods at runtime using reflection at runtime,

See here :

       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);   

Hope code will clarifies ...If any any confusion do let me know I'll edit my question accordingly.

I am stuck here , I'll be obliged if you help me out.(I am confused about "dynamic" keyword might hope it solves the problem)

Is there any need to generate C++/CLI wrappers? and if in which context?
Regards
Usman

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

妄司 2024-09-24 05:11:13

只需将参数的直接放入数组中即可。对于 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 中进行构造,您可以使用 -> 来访问 C# 中的成员。不过,我不确定你的 API 的内存管理规则是什么;您最终可能需要释放该结构,但具体如何执行应由您尝试调用的 API 的文档进行描述。

Just put the values of your arguments directly into the array. For out/ref parameters, the corresponding elements of the array will be replaced by new values returned by the function.

For the double pointer, by far the easiest approach is to use /unsafe and unmanaged pointers, like so (assuming the parameter is used by the method to return a value):

 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);

After you'll get the pointer to struct in pWesContext, you can use -> to access the members in C#. I'm not sure what memory management rules for your API are, though; it may be that you will, eventually, need to free that struct, but how exactly to do that should be described by the documentation of the API you're trying to call.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文