You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#调用C++ DLL时结构体封送数据异常,如何修正?

问题分析与修正方案

核心问题

数据错位的根本原因是C#结构体的类型映射和内存对齐规则与C++不匹配:

  1. 类型不匹配:C++中unsigned long在32位环境下是4字节无符号整数,你错误地用了C#的long(8字节)来映射,直接导致后续字段的内存偏移全部错乱。
  2. 内存对齐不匹配:C默认的结构体对齐规则(32位环境)是4字节,你设置了Pack=8,导致结构体的内存填充逻辑与C不一致,进一步加剧数据错位。

修正后的代码

1. 正确的C#结构体定义

[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct USB_DEVICE_INFO
{
    public byte ucSpeed;
    // 对应C++的unsigned long(32位环境下4字节无符号整数)
    public uint ulLength;
    public byte ucBulkInPipe;
    public byte ucBulkOutPipe;
    public byte ucInterruptPipe;
}

如果需要显式指定封送类型,也可以写成:

[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct USB_DEVICE_INFO
{
    public byte ucSpeed;
    [MarshalAs(UnmanagedType.U4)]
    public uint ulLength;
    public byte ucBulkInPipe;
    public byte ucBulkOutPipe;
    public byte ucInterruptPipe;
}

2. 优化后的DLL导入声明(可选但更严谨)

如果C++的_InitialiseDevice使用的是WINAPI(即__stdcall)调用约定,显式指定调用约定可以避免潜在的栈平衡问题:

[DllImport(@"32.dll", CallingConvention = CallingConvention.StdCall)]
public static extern bool _InitialiseDevice(out USB_DEVICE_INFO pDevInfo);

验证逻辑

修正后的C#结构体内存布局与C++完全一致(32位环境下):

  • ucSpeed占1字节,自动填充3字节以对齐到4字节边界
  • ulLength占4字节
  • 后续三个byte字段各占1字节,最后填充1字节使整个结构体大小为12字节(4的倍数,符合默认对齐规则)

这样C++填充的字段值就能准确映射到C#结构体的对应成员中。

内容的提问来源于stack exchange,提问作者Nick Pitman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 07:28:14