通过从.Net 4.5更新到.Net 4.5.1来破坏P / Invoke方法

时间:2013-12-04 13:12:31

标签: c# .net pinvoke .net-4.5

我的应用程序中有一个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所怀疑的。

2 个答案:

答案 0 :(得分:2)

我唯一能找到问题代码的错误就是返回值。默认情况下,编组将假定本机代码返回4字节BOOL。你应该写这样的pinvoke:

[DllImport(...)]
[return: MarshalAs(UnmanagedType.I1)]
internal static extern bool OMBOpen(...);

但是,我看不出这会导致您报告的错误。我宁愿怀疑实际问题在于代码中没有问题。

<强>参考文献:

  1. http://blogs.msdn.com/b/jaredpar/archive/2008/10/14/pinvoke-and-bool-or-should-i-say-bool.aspx
  2. http://www.greengingerwine.com/index.php/2011/08/always-marshal-bool-return-types-when-using-pinvoke/
  3. http://msdn.microsoft.com/en-us/library/ms182206.aspx

答案 1 :(得分:2)

尝试将void方法的结果赋给变量时,抛出异常“无法将类型'void'隐式转换为'object'”。虽然这通常是编译器错误,但如果在执行期间看到它,则通常是由于动态调用方法(例如使用动态关键字或使用IronPython等动态语言)而发生的。

.NET 4.5.1为Marshal.SizeOfMarshal.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)'