我的应用程序中有一个P / Invoke调用,它通过用C ++编写的API(.dll文件)与外部硬件进行通信
这个方法非常有效,直到我安装了最新的.Net 4.5.1,并且没有进行任何代码更改它现在抛出一个异常:“不能隐式地将类型'void'转换为'object'”
有什么我应该检查以使我的应用程序与.Net 4.5.1兼容吗?回滚到以前的框架是我发现使它工作的唯一方法!
[DllImport("TestAPI", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
internal static extern bool OMBOpen(int VID, int PID, int CID,
StringBuilder description,
int bufferSize);
C ++中方法的原生声明
TESTAPI_API
bool OMBOpen(int VID,int PID,int IID,char* buffer,int bufferSize);
编辑:
最后问题结果是根本没有使用上面的方法调用本身,而是从指向数据结构的指针编组数据(参见接受的答案),这是代码中的其他部分,如David Heffernan wiseley所怀疑的。
答案 0 :(得分:2)
我唯一能找到问题代码的错误就是返回值。默认情况下,编组将假定本机代码返回4字节BOOL
。你应该写这样的pinvoke:
[DllImport(...)]
[return: MarshalAs(UnmanagedType.I1)]
internal static extern bool OMBOpen(...);
但是,我看不出这会导致您报告的错误。我宁愿怀疑实际问题在于代码中没有问题。
<强>参考文献:强>
答案 1 :(得分:2)
尝试将void方法的结果赋给变量时,抛出异常“无法将类型'void'隐式转换为'object'”。虽然这通常是编译器错误,但如果在执行期间看到它,则通常是由于动态调用方法(例如使用动态关键字或使用IronPython等动态语言)而发生的。
.NET 4.5.1为Marshal.SizeOf
和Marshal.PtrToStructure
引入了重载,动态方法调用可能会在某些情况下选择新的重载。请参阅Microsoft KB2909958。上述异常不是来自P / Invoke本身,而是来自随后的封送操作。
解决这类问题的最简单方法是在调用中引入一个强制转换,以确保解决正确的方法。
#Code from 4.5
dynamic dynamicVar = ...
object boxedStruct = Marshal.PtrToStructure(myPtr, dynamicVar.GetType());
// Above resolves to 'object Marshal.PtrToStructure(IntPtr, Type)' in 4.5
// and resolves to 'void Marshal.PtrToStructure<T>(IntPtr, T)' in 4.5.1
int size = Marshal.SizeOf(dynamicVar.GetType());
// Above resolves to 'object Marshal.SizeOf(Type)' in 4.5
// and resolves to 'void Marshal.SizeOf<T>(T)' in 4.5.1
#Fixed for 4.5.1
dynamic dynamicVar = ...
object boxedStruct = Marshal.PtrToStructure(myPtr, (Type)dynamicVar.GetType());
// Adding the cast forces the code to resolve to
// 'object Marshal.PtrToStructure(IntPtr, Type)'
int size = Marshal.SizeOf((Type)dynamicVar.GetType());
// Adding the cast forces the code to resolve to
// 'int Marshal.SizeOf(Type)'