c#调用非托管dll里的函数,函数的参数时结构体,如何正确封送结构体?

这是dll里结构体的定义。

/* 连接用户信息结构定义*/
typedefstruct tmConnectInfo_t
{
unsigned int dwSize; //该结构的大小,必须填写
char pIp[32]; //连接服务器的IP地址
int iPort; //服务器连接的端口
char szUser[32]; //登录用户名
char szPass[32]; //登录用户口令
int iUserLevel; //登录用户级别,主要用户DVS的一些互斥访问资源
unsigned char pUserContext[USER_CONTEXT_SIZE]; //用户自定义数据
}tmConnectInfo_t;
我用 c# 语言,多次尝试封送结构体,都无法正确执行。
第一种错误写法:
//报错,提示 指定的数组不属于需要的类型
//[StructLayout(LayoutKind.Explicit)]
//public struct tmConnectInfo_t
//{
// [System.Runtime.InteropServices.FieldOffsetAttribute(0)]
// public int dwSize;
// [System.Runtime.InteropServices.FieldOffsetAttribute(4)]
// public char[] pIp;
// [System.Runtime.InteropServices.FieldOffsetAttribute(36)]
// public int iPort;
// [System.Runtime.InteropServices.FieldOffsetAttribute(40)]
// public char[] szUse;
// [System.Runtime.InteropServices.FieldOffsetAttribute(72)]
// public char[] szPass;
// [System.Runtime.InteropServices.FieldOffsetAttribute(104)]
// public int iUserLevel;
// [System.Runtime.InteropServices.FieldOffsetAttribute(108)]
// public char[] pUserContext;
//}
第二种错误写法:
//现在是,调试时,提示内存损坏,运行exe ,程序停止工作。
//[StructLayout(LayoutKind.Sequential)]
//public struct tmConnectInfo_t
//{
// public uint dwSize;
// public string pIp;
// public int iPort;
// public string szUser;
// public string szPass;
// public int iUserLevel;
// public string pUserContext;
//}
该dll 是用 c++ 编写的,不是我编写的。我看过非托管dll封送结构体的资料,都没有解决问题,希望能熟悉c#语言和非托管DLL的程序员帮忙。
就是结构体的写法,使用 C# 语言写出来。

第1个回答  推荐于2016-06-23
C# 结构体可以这样定义
/// <summary>
/// 卷头记录 Reel Trailer Record卷尾格式也一样 共128字节
/// <summary>
[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] // [StructLayout(LayoutKind.Sequential, Pack = 1)] //顺序排列,并按1字节对齐
public struct ReelHeaderRecord
{
/// <summary>
/// 0000-0001 逻辑记录头
/// </summary>
[MarshalAs(UnmanagedType.U2, SizeConst = 2)]
public ushort LogicalRecordHeader;

/// <summary>
/// 0002-0007 服务名称6个字节
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst =6)]
public byte[] ServiceName;

/// <summary>
/// 0008-00013 空白1 默认值为0x20
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public byte[] Blank1;

/// <summary>
/// 00014-00021 日期 ASCII码表示
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst =8)]
public byte[] Data;

/// <summary>
/// 00022-00023 空白2 默认值为0x20
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public byte[] Blank2;

/// <summary>
/// 00024-00027 数据来源
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] OriginofDate ;

/// <summary>
/// 00028-00029 空白3 默认值为0x20
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public byte[] Blank3;

/// <summary>
/// 00030-00037 卷名字
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] ReelName ;

/// <summary>
/// 00038-00039 空白4 默认值为0x20
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public byte[] Blank4;

/// <summary>
/// 00040-00041 卷间逻辑序号
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public byte[] ReelContinuationNumber ;

/// <summary>
/// 00042-00043 空白5 默认值为0x20
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public byte[] Blank5;

/// <summary>
/// 00044-00051 前邻卷名
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] PreviousReelName ;

/// <summary>
/// 00052-00053 空白6 默认值为0x20
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public byte[] Blank6;

/// <summary>
/// 00054-00127注释
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 74)]
public byte[] Note;

}
网上有C#结构体转数组 数组转结构体的代码 字节数不少下来就可以用了

导入c++ DLL 可以像这样 DLL放到你运行程序的目录

[DllImport("你的DLL名称.dll")]
static extern void WriteData();
[DllImport("lisLib.dll")]
static extern void CloseData();

如果平台不对导入 要在 [DllImport 后面加一些语句就好,现在忘记了 以前用过本回答被提问者和网友采纳
相似回答