首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > C# >

:C# 调用C++ 回调函数的有关问题,将无效 VARIANT 传递给 CLR 会导致意外的错误

2013-08-16 
求救:C# 调用C++ 回调函数的问题,将无效 VARIANT 传递给 CLR 会导致意外的异常客户给的dll文件,用c#调用,

求救:C# 调用C++ 回调函数的问题,将无效 VARIANT 传递给 CLR 会导致意外的异常
客户给的dll文件,用c#调用,其中有个方法是要传回调函数c++是这样定义的
1、On_exec_result SetExecResult(On_exec_result pHandler);
2、typedef void(CALLBACK* On_exec_result)(const TAnswer *pAnswer);
3、TAnswer{
  char chInfo [64]
  int nAnswer
  int nMarkets
  char chMarketFlag [32][4]
  int nDynDate [32]
}
(真搞不明白搞不明白SetExecResult的返回值也是个On_exec_result函数?)
我c#是这样写的:
 1、 [DllImport("TAPI.dll", CallingConvention = CallingConvention.Cdecl)]
   public static extern void SetExecResult(On_exec_result pHandler);
 2、public delegate void On_exec_result (TAnswer tAnswer);
 3、public struct TAnswer 
     {        
         [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 64)]
         public byte[] chInfo;
         [MarshalAs(UnmanagedType.I4)]
         public int nAnswer;
         [MarshalAs(UnmanagedType.I4)]
         public int nMarkets;
         [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 3 * 16)]
         public byte[] chMarketFlag;
         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
         public byte[] nDynDate;
    }
  调用的地方:
   On_exec_result tHandler = new On_exec_result(OnExecHandler);
   SetExecResult(tHandler);
   public void OnExecHandle(TAnswer tAnswer)
   {
       Logger.Info(tAnswer.nAnswer);
   }

运行的时候错误:从非托管 VARIANT 转换为托管对象的过程中检测到无效 VARIANT。将无效 VARIANT 传递给 CLR 会导致意外的异常、损坏或数据丢失
    C# C++ struct callback


[解决办法]
         [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 64)]
         public byte[] chInfo;
         [MarshalAs(UnmanagedType.I4)]
         public int nAnswer;
         [MarshalAs(UnmanagedType.I4)]
         public int nMarkets;
         [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 3 * 16)]
         public byte[] chMarketFlag; //二维数组尺寸似乎不对
         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
         public byte[] nDynDate; //这里要求的 int ,
[解决办法]
应该是struct的定义有问题吧,楼上应该是正解
[解决办法]
楼主,嗯,花了我2小时,我在VS2010里面模拟了你的问题,得到正确结构返回了,不像你只传了一个整数。
问题就是在传递结构的时候出错,我建议你还是多搜索一下网上关于C#、C++互操作的文章。
1.SetExecResult返回是个函数指针是为了调用C#里面的相应函数(委托)。调用可以是双方的,而不只是C#单方向调用C++的函数。
2.正如楼上说的,你就托管代码转换成非托管代码时候用MarshalAs显示定义数组元素所占位置大小是可取的,但是你改后的SizeConst还有一个错的,没算对,最后一个是int型数组,应该定义成32*4。
3.最后在C#定义结构时显示的声明[structLayout(LayoutKind.Sequential)],虽然MSDN上说默认是这个选项,但我建议你还是显示写出来。字段顺序很重要。
4.在你引用DLL是声明可CallingConvention.Cdecl,但是DLL中的是函数是CALLBACK,这个在定义是#define CALLBACK __stdcall。
还有一些小问题就不讲了,你先试试看,不行的话,我给你贴我的代码。

热点排行