none
C++通过反射调用C#的Dll接口时,接口参数为自定义类对象的数组,应如何设定参数? RRS feed

  • 问题

  • 关于在托管C++程序中通过反射调用C#的Dll的问题,请大侠帮看看,详细如下:

    有一个C#的DLL(A.dll)中有如下一个函数:
     public bool Test(int count, Detail[] Details)

    其中Detail是一个自定义类型,定义如下:
         public class Detail
         {
             public string MsgCode { get; set; }
             public string[] MsgParams { get; set; }
         }

    我现在想要在C++程序中使用上面这个接口函数,这个C++程序是托管程序。
     下面是我的代码(简化版),可是运行时有问题,详细见下:

        //创建C#类实例
         Assembly^ assem = Assembly::LoadFrom(gcnew String("A.dll"));
         Type^ type = assem->GetType("libA.XXX");
         Object^ obj = Activator::CreateInstance(type);

        // 创建自定义类型数组
         Type^ type_Details = assem->GetType("libA.Detail");
         array<Object^>^ Details =  gcnew array<Object^>(5);
         for( int i = 0; i < 5; ++i )
         {
             Details[i] = Activator::CreateInstance(type_Details);
         }

         MethodInfo^ method = type->GetMethod("Test");
         Object^ obj_result;
         array<Object^>^args;
         args = gcnew array<Object^>(4);
         args[ 0 ] = 1;
         args[ 1 ] = Details;//这个是输出参数
         obj_result = method->Invoke(obj, args); // 错误信息:不能转换类型'System.Object[]'到'libA.Detail[]'

    现在的问题是调用的C#函数的参数是自定义类型的数组时就不好使,
     如果不是数组,或者是内置类型数组都没有问题。

    请问应该如何传递参数?

               
    2012年12月11日 7:33

答案

  • 真不容易,终于找到个折衷办法,第一次用C++/CLR,不太熟悉,只能这样了。

    Type^ type_responseDetails = assem->GetType("libA.Detail");

    Array^ arrDetails = Array::CreateInstance(type_responseDetails ,count);

    array<Detail^>^ Details = (array<Detail^>^)arrDetails;  // 此强制转换成功

    你可以尝试使用 arrDetails 来作为参数与C# DLL 交互。


    • 已编辑 Skyseer 2012年12月13日 9:03
    • 已标记为答案 holmesning 2012年12月13日 10:58
    2012年12月13日 9:01

全部回复

  • array<Object^>^  不对,你可以用 MakeGenericType 来动态创建 array<Details>
    2012年12月11日 9:24
  • 感谢你的回复,我试验了MakeGenericType的方法,但没有成功。可能是代码不正确。

    能否举个代码的例子,如何使用MakeGenericType 来动态创建 array<Details>?

    2012年12月13日 1:17
  • Type generic = typeof(array<>);

    generic=generic.MakeGenericType(new Type{type_Details };

    var Details  = Activator::CreateInstance(generic);

    2012年12月13日 1:48
  • 上面代码是C#的,c++中模仿着做了一个。

    typeof(array<>);这句编译有错误,在c++中改为array<Object^>::typeid

    但在new Type{type_Details}时会有错误,提示我抽象的类型转换失败。

    我又尝试了其他方法动态创建,CreateInstance+MakeArrayType来动态创建对象,代码如下

    Type^ type_responseDetails = assem->GetType("libA.Detail");  
    Object^ Details =

       Activator::CreateInstance(type_responseDetails->MakeArrayType(count));

    运行时遇到新的错误:"No parameterless constructor defined for this object."

    但C#程序中libA.Detail已经有无参数的构造函数。为什么还有错误提示呢?挺困惑。

    2012年12月13日 8:04
  • 这个错误应该针对你的 array<Detail> 这个类型来的,不是指你的 Detail 没有无参构造函数。

    2012年12月13日 8:42
  • 真不容易,终于找到个折衷办法,第一次用C++/CLR,不太熟悉,只能这样了。

    Type^ type_responseDetails = assem->GetType("libA.Detail");

    Array^ arrDetails = Array::CreateInstance(type_responseDetails ,count);

    array<Detail^>^ Details = (array<Detail^>^)arrDetails;  // 此强制转换成功

    你可以尝试使用 arrDetails 来作为参数与C# DLL 交互。


    • 已编辑 Skyseer 2012年12月13日 9:03
    • 已标记为答案 holmesning 2012年12月13日 10:58
    2012年12月13日 9:01
  • to DroidXgnaW

    按照上面的方法,已经解决了。

    非常感谢你,这个问题困扰我一周了,谢谢。

    2012年12月13日 11:01