gpt4 book ai didi

c# - 我应该如何为互操作声明这个 C 结构?

转载 作者:太空狗 更新时间:2023-10-29 17:23:19 25 4
gpt4 key购买 nike

我必须在我正在开发的应用程序中使用遗留的 C 例程。此处的代码有效,但我必须将几乎所有字段转换为 char 数组才能使用它。有更好的方法吗?我尝试了一些使用字符串的版本,但都无济于事。

这是在原始头文件中找到的代码...

typedef struct PXUCAMR
{
char xumrversaocomc01;
char xumrretcomc02[2];
char xumrretusuc02[2];
char xumrcodfalhac05[5];
char xumrfiller1c01;
char xumrtipoambclic01;
char xumrambientec01;
char xumrconvertec01;
char xumroperacaoc01;
char xumropcaoexec01;
xumrcom_t *xumrhandleconnb31;
char xumrreshconnc04[4];
long xumrtamdadosb31;
char xumrtransacaosrvc08[8];
char xumrtransrvdb2c04[4];
char xumrpgmservidorc08[8];
char xumrversaopgmsrvc02[2];
char xumrconectardbc01;
char xumrusuariosrvc08[8];
char xumrsenhasrvc08[8];
char xumridcriptc08[8];
char xumrpgmclientec08[8];
char xumrversaopgmclientec02[2];
char xumridclientec20[20];
char xumrtipoidclientec01;
char xumrusuarioclientec08[8];
char xumrprodutophac16[16];
char xumridservidorc30[30];
char xumrdadosc10000[10000];
}
pxucamr_t;

...这是我在 C# 应用程序中使用的声明...

[StructLayout(LayoutKind.Sequential)]
internal struct PXUCAMR
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public char[] xumrversaocomc01;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public char[] xumrretcomc02;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public char[] xumrretusuc02;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
public char[] xumrcodfalhac05;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public char[] xumrfiller1c01;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public char[] xumrtipoambclic01;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public char[] xumrambientec01;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public char[] xumrconvertec01;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public char[] xumroperacaoc01;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] // 16
public char[] xumropcaoexec01;
[MarshalAs(UnmanagedType.I4)]
public int xumrhandleconnb31;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public char[] xumrreshconnc04;
[MarshalAs(UnmanagedType.I4)]
public int xumrtamdadosb31;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] // 36
public char[] xumrtransacaosrvc08;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public char[] xumrtransrvdb2c04;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public char[] xumrpgmservidorc08;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public char[] xumrversaopgmsrvc02;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public char[] xumrconectardbc01;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] // 67
public char[] xumrusuariosrvc08;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public char[] xumrsenhasrvc08;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public char[] xumridcriptc08;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public char[] xumrpgmclientec08;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] // 93
public char[] xumrversaopgmclientec02;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
public char[] xumridclientec20;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] // 114
public char[] xumrtipoidclientec01;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public char[] xumrusuarioclientec08;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] // 138
public char[] xumrprodutophac16;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 30)] // 168
public char[] xumridservidorc30;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10000)]
public char[] xumrdadosc10000;
}

有更好的方法吗?

编辑:

根据 Justin Rudd 的回答,我测试了这个版本的结构:

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
internal struct PXUCAMRV3
{
public char xumrversaocomc01;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 2)]
public string xumrretcomc02;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 2)]
public string xumrretusuc02;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 5)]
public string xumrcodfalhac05;

public char xumrfiller1c01;
public char xumrtipoambclic01;
public char xumrambientec01;
public char xumrconvertec01;
public char xumroperacaoc01;
public char xumropcaoexec01; // 16

[MarshalAs(UnmanagedType.I4)]
public int xumrhandleconnb31;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
public string xumrreshconnc04;
[MarshalAs(UnmanagedType.I4)]
public int xumrtamdadosb31;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)] // 36
public string xumrtransacaosrvc08;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
public string xumrtransrvdb2c04;

/* ... same pattern to remaining fields ... */
}

我只在一些领域尝试过并成功,但我改变了所有,返回值出现问题。例如,我发送这个...

pxucamrv3.xumrpgmservidorc08 = "PHAPREXW";
pxucamrv3.xumrversaopgmsrvc02 = "01";
pxucamrv3.xumrpgmclientec08 = "PHAOCLXN";
pxucamrv3.xumrversaopgmclientec02 = "02";
pxucamrv3.xumridservidorc30 = "N006";
pxucamrv3.xumrcodfalhac05 = "00000";
pxucamrv3.xumrretcomc02 = "00";
pxucamrv3.xumrretusuc02 = "00";

...然后得到这个...

pxucamrv3.xumrpgmservidorc08 == "PHAPREX"
pxucamrv3.xumrversaopgmsrvc02 == "0"
pxucamrv3.xumrpgmclientec08 == "PHAOCLX"
pxucamrv3.xumrversaopgmclientec02 == "0"
pxucamrv3.xumridservidorc30 == "N006"
pxucamrv3.xumrcodfalhac05 == "01 "
pxucamrv3.xumrretcomc02 == "W"
pxucamrv3.xumrretusuc02 == "0"

...如我们所见,字符串的编码/解码存在问题。字符字段看起来没问题。这不是映射问题,因为字符串字段的开头是可以的。但它似乎正在截断字符串的末尾。而且我的测试调用不应该返回错误(使用前面的结构,它有效),所以 C 例程也没有收到它应该接收的数据(在 xumrretcomc02 中应该只返回零;返回的“W”表示有错误,但我有很多以“W”开头的错误代码。

我会继续深入研究它。

再次抱歉我的英语不好。 :)

最佳答案

我最终使用字节数组作为结构的表示,并使用构建器来设置值。性能提升不大,但确实存在。还有内存优势,因为我可以将它固定在内存中并将其直接发送到非托管例程。它实际上帮助我解决了另一个问题:这个结构有两个版本,具有不同的 xumrdadosc10000 大小......原来的是 10000 字节,但新的是 200000 字节,但名称是相同的兼容性目的。因此,我可以在构造函数中创建合适的大小,然后开始。

/// <summary>Builds PXUCAMR/PXUCAMRV3 as a byte array.</summary>
internal class PxucamrBuilder
{
internal byte[] Pxucamr;

/// <summary>Get/set field xumrversaocomc01, offset 0, size 1 byte.</summary>
internal string StructureVersion
{
get { return Encoding.ASCII.GetString(this.Pxucamr, 0, 1); }
set { Encoding.ASCII.GetBytes(value, 0, 1, this.Pxucamr, 0); }
}

/// <summary>Get/set field xumrambientec01, offset 12, size 1 byte.</summary>
internal string Context
{
get { return Encoding.ASCII.GetString(this.Pxucamr, 12, 1); }
set { Encoding.ASCII.GetBytes(value, 0, 1, this.Pxucamr, 12); }
}

/// <summary>Get/set field xumrcodfalhac05, offset 5, size 5 byte.</summary>
internal string ErrorCode
{
get { return Encoding.ASCII.GetString(this.Pxucamr, 5, 5); }
set { Encoding.ASCII.GetBytes(value, 0, 5, this.Pxucamr, 5); }
}

/// <summary>Get/set field xumridservidorc30, offset 130, size 30 bytes.</summary>
internal string ServerId
{
get { return Encoding.ASCII.GetString(this.Pxucamr, 130, 30); }
set { Encoding.ASCII.GetBytes(value, 0, value.Length, this.Pxucamr, 130); }
}

/// <summary>Get/set field xumrtamdadosb31, offset 24, size 4 byte.</summary>
internal int DataSize
{
get
{
byte[] bytes = new byte[4];
Array.Copy(this.Pxucamr, 24, bytes, 0, 4);
return this.ByteArrayToInt32(bytes);
}
set
{
byte[] bytes = this.Int32ToByteArray(value);
Array.Copy(bytes, 0, this.Pxucamr, 24, 4);
}
}

/* ... same pattern to remaining fields ... */
}

可以使用 Marshal.OffsetOf 方法轻松找到偏移量。

因为我正在使用这个答案,所以我会将这个答案标记为正确答案。但如果出现更好的答案,我可以更改它。我仍然愿意尝试新的想法!

关于c# - 我应该如何为互操作声明这个 C 结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1702900/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com