问题:需要在运行时使用反射传递指针作为参数来进行 COM InterOp?
我需要在运行时使用反射来制作 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
只需将参数的值直接放入数组中即可。对于
out
/ref
参数,数组的相应元素将被函数返回的新值替换。对于双指针,到目前为止,最简单的方法是使用
/unsafe
和非托管指针,如下所示(假设方法使用参数来返回值):要在
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):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.