c# - 从 C++ 编码到 C# 时 CLR 崩溃

标签 c# c++ .net marshalling unmanaged

我正在使用尼康的 API 来控制显微镜。 API 是用 C++ 编写的,而我正在用 C# 实现驱动程序。要打开与显微镜的连接,我必须使用具有以下语法的 Open 方法:

lx_result MIC_Open ( const lx_int32 iDeviceIndex, lx_uint64& uiConnectedAccessoryMask, const lx_uint32 uiErrMsgMaxSize, lx_wchar* pwszErrMsg)

如果我按如下方式编码该技术,则每当执行垃圾收集时代码就会崩溃:

[DllImport("/filepath/Ni_Mic_Driver.dll")]
protected static extern int MIC_Open ( int deviceIndex , ref ulong accessoryMask , uint errorMessageMaxSize , [MarshalAsAttribute(UnmanagedType.LPWStr)] string error);

抛出错误代码为 80131506 的 0xc000005 异常,表示垃圾收集器已尝试处理具有无效指针的对象。 Visual Studio 2013 生成的错误消息表明:

“此错误可能是 CLR 中的错​​误,或者是用户代码的不安全或不可验证部分中的错误。 此错误的常见来源包括 COM-Interop 或 PInvoke 的用户编码错误,这可能会损坏堆栈。”

按照消息建议,我将编码调整为以下内容,这不会导致 CLR 崩溃。

[DllImport("/filepath/Ni_Mic_Driver.dll")]
protected static extern int MIC_Open ( int deviceIndex , ref ulong accessoryMask , uint errorMessageMaxSize , [MarshalAsAttribute(UnmanagedType.LPStr)] string error);

我很困惑,因为我的理解是 wchar* 指示指向以 null 结尾的 16 位 Unicode 字符的字符串的指针,它应该映射到 UnamagedType.LPWStr。但是,该代码仅在我使用 UnmanagedType.LPStr 时才有效。

下面的也可以,但是需要更多的工作才能提取相应的字符串。

[DllImport("/filepath/Ni_Mic_Driver.dll")]
protected static extern int MIC_Open ( int deviceIndex , ref ulong accessoryMask , uint errorMessageMaxSize , IntPtr errorPointer );

有没有想过为什么 UnamagedType.LPWStr 在使用 UnmanagedType.LPStr 或 IntPtr 时会导致崩溃?

最佳答案

感谢 Hans Passant 的推荐。我按如下方式更正了编码:

[DllImport("/filepath/Ni_Mic_Driver.dll")]
protected static extern int MIC_Open ( int deviceIndex , ref ulong accessoryMask , uint errorMessageMaxSize , [MarshalAsAttribute(UnmanagedType.LPWStr)] StringBuilder errorString);

然后我使用这个方法如下(这里简化展示):

NikonDefinitions.accessory = 0;
int errorMessageCapacity = 256;
int nikonErrorMessageMaxSize = errorMessageCapacity - 1;
StringBuilder errorMessage = new StringBuilder(errorMessageCapacity);
int nikonReturn = NikonDefinitions.MIC_Open(Convert.ToInt32(1),ref NikonDefinitions.accessory,nikonErrorMessageMaxSize,errorMessage);

关于c# - 从 C++ 编码到 C# 时 CLR 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25794620/

相关文章:

c# - 如何将 DataTable 转换为 List<object>?

c# - 如何从 C# 中的 wsdl SOAP 请求信封

c# - 用于从智能手机上的 GPS 位置获取附近商店名称的 API

c++ - 揭秘 lpthreads 下的 gcc

c++ - 在类中使用 fstream 时出现问题

c# - 如何在继承的ControlDesigner类中获取ITypeDescriptorContext和IServiceProvider

c# - ZipFile.ExtractToDirectory 抛出长文件名

c# - 当应用程序关闭时,数据库连接会立即关闭吗?

C++ 模板内部

c# - .NET 并发集合可以用于 x32 到 x64 的进程间通信吗?