求救:C# 调用C++ 回调函数的问题,将无效 VARIANT 传递给 CLR 会导致意外的异常

you34 2013-08-05 01:47:50
客户给的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 会导致意外的异常、损坏或数据丢失
...全文
413 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
you34 2013-08-12
  • 打赏
  • 举报
回复
测试代码果然能运行,谢谢dav0913
you34 2013-08-12
  • 打赏
  • 举报
回复
多谢dav0913,今天才看到。谢谢。貌似你的不是c#?俺再研究研究.....
you34 2013-08-12
  • 打赏
  • 举报
回复
貌似用unsafe很多地方都有问题,唉,悲剧..
you34 2013-08-09
  • 打赏
  • 举报
回复
有木有人啊。。
dav0913 2013-08-09
  • 打赏
  • 举报
回复
[DllImport(@"D:\Visual Studio 2010\Projects\TestCPPDLL\Debug\TestCPPDLL.dll", EntryPoint = "SetExecResult")] extern unsafe static void SetExecResult(CSCallbackp pAnswer); unsafe delegate void CSCallbackp(TAnswer* pAnswer); [StructLayout(LayoutKind.Sequential)] unsafe struct TAnswer { public fixed byte chInfo[64]; public int nAnswer; public int nMarkets; public fixed byte chMarketFlag[128]; public fixed int nDynDate[32]; } 调用地方: unsafe { callbackp = CSCallbackpFunction; SetExecResult(callbackp); } unsafe static void CSCallbackpFunction(TAnswer* pAnswer) { //ToDo something; }
you34 2013-08-08
  • 打赏
  • 举报
回复
额。休假1天归来。dav0913兄弟呢,求代码....谢谢
you34 2013-08-06
  • 打赏
  • 举报
回复
万分感谢dav0913兄弟,我按照您的方式,最后一个数组换成32*4还是同样的错误,如果CallingConvention.Cdecl改成CallingConvention.StdCall,会抛个“调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配”的错误。另外结构体有声明[structLayout(LayoutKind.Sequential)],呵呵。能做到这一步已经连续网上搜了n天资料的结果了,实在木有办法才来这里发帖。。麻烦看看您的代码,多谢多谢!
dav0913 2013-08-05
  • 打赏
  • 举报
回复
楼主,嗯,花了我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。 还有一些小问题就不讲了,你先试试看,不行的话,我给你贴我的代码。
you34 2013-08-05
  • 打赏
  • 举报
回复
UnmanagedType.ByValTStr是把托管代码转化为非托管代码的数组,SizeConst是数组长度。 抛出来的错误是不是跟这个结构体的定义有关?
you34 2013-08-05
  • 打赏
  • 举报
回复
哦,请教下这个struct应该怎样定义?
FTD_2009 2013-08-05
  • 打赏
  • 举报
回复
应该是struct的定义有问题吧,楼上应该是正解
you34 2013-08-05
  • 打赏
  • 举报
回复
多谢楼上兄弟回复! 我换成 [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 64)] public byte[] chInfo; [MarshalAs(UnmanagedType.I4)] public int nAnswer; [MarshalAs(UnmanagedType.I4)] public int nMarkets; [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 32 * 4)] public byte[] chMarketFlag; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public int[] nDynDate; 还是一样的错误,感觉好像不是这个结构定义的问题,我自己按照一样的结构定义写了个c++ dll做测试 extern "C" __declspec(dllexport) void Test(TAnswer* mystruct) { mystruct->nAnswer=1; } 然后c# : [DllImport("standerMFC.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int Test(ref TAnswer tAnswer); TAnswer tAnswer=new TAnswer (); Test(ref sAnswer); Console.WriteLine(tAnswer.nAnswer); 能得到1
真相重于对错 2013-08-05
  • 打赏
  • 举报
回复
[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 ,
真相重于对错 2013-08-05
  • 打赏
  • 举报
回复
struct 定义错误

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧