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 会导致意外的异常、损坏或数据丢失
14 个解决方案
#1
struct 定义错误
#2
[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 ,
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 ,
#3
多谢楼上兄弟回复!
我换成
[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
我换成
[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
#4
应该是struct的定义有问题吧,楼上应该是正解
#5
哦,请教下这个struct应该怎样定义?
#6
UnmanagedType.ByValTStr是把托管代码转化为非托管代码的数组,SizeConst是数组长度。
抛出来的错误是不是跟这个结构体的定义有关?
抛出来的错误是不是跟这个结构体的定义有关?
#7
楼主,嗯,花了我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。
还有一些小问题就不讲了,你先试试看,不行的话,我给你贴我的代码。
问题就是在传递结构的时候出错,我建议你还是多搜索一下网上关于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。
还有一些小问题就不讲了,你先试试看,不行的话,我给你贴我的代码。
#8
万分感谢dav0913兄弟,我按照您的方式,最后一个数组换成32*4还是同样的错误,如果CallingConvention.Cdecl改成CallingConvention.StdCall,会抛个“调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配”的错误。另外结构体有声明[structLayout(LayoutKind.Sequential)],呵呵。能做到这一步已经连续网上搜了n天资料的结果了,实在木有办法才来这里发帖。。麻烦看看您的代码,多谢多谢!
#9
额。休假1天归来。dav0913兄弟呢,求代码....谢谢
#10
有木有人啊。。
#11
[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;
}
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;
}
#12
多谢dav0913,今天才看到。谢谢。貌似你的不是c#?俺再研究研究.....
#13
测试代码果然能运行,谢谢dav0913
#14
貌似用unsafe很多地方都有问题,唉,悲剧..
#1
struct 定义错误
#2
[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 ,
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 ,
#3
多谢楼上兄弟回复!
我换成
[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
我换成
[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
#4
应该是struct的定义有问题吧,楼上应该是正解
#5
哦,请教下这个struct应该怎样定义?
#6
UnmanagedType.ByValTStr是把托管代码转化为非托管代码的数组,SizeConst是数组长度。
抛出来的错误是不是跟这个结构体的定义有关?
抛出来的错误是不是跟这个结构体的定义有关?
#7
楼主,嗯,花了我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。
还有一些小问题就不讲了,你先试试看,不行的话,我给你贴我的代码。
问题就是在传递结构的时候出错,我建议你还是多搜索一下网上关于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。
还有一些小问题就不讲了,你先试试看,不行的话,我给你贴我的代码。
#8
万分感谢dav0913兄弟,我按照您的方式,最后一个数组换成32*4还是同样的错误,如果CallingConvention.Cdecl改成CallingConvention.StdCall,会抛个“调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配”的错误。另外结构体有声明[structLayout(LayoutKind.Sequential)],呵呵。能做到这一步已经连续网上搜了n天资料的结果了,实在木有办法才来这里发帖。。麻烦看看您的代码,多谢多谢!
#9
额。休假1天归来。dav0913兄弟呢,求代码....谢谢
#10
有木有人啊。。
#11
[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;
}
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;
}
#12
多谢dav0913,今天才看到。谢谢。貌似你的不是c#?俺再研究研究.....
#13
测试代码果然能运行,谢谢dav0913
#14
貌似用unsafe很多地方都有问题,唉,悲剧..