我必须在我正在开发的应用程序中使用遗留的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#app中使用的声明......
[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"
...正如我们所看到的,字符串的编组/解组存在问题。 char字段看起来还不错。这不是映射问题,因为字符串字段的开始是可以的。但它似乎正在截断字符串的结尾。并且我的测试调用不应该返回错误(使用前面的结构,它可以工作),因此C例程也没有收到数据,因为它也应该(在 xumrretcomc02中只返回零;返回“W”表示存在错误,但我有很多以“W”开头的错误代码。
我会继续深入研究它。
再次,抱歉我的英语不好。 :)
答案 0 :(得分:5)
我最终使用字节数组作为结构的表示,并使用构建器来设置值。性能提升并不大,但它确实存在。并且还有内存优势,因为我可以将其固定在内存中并将其直接发送到非托管例程。它实际上帮助我解决另一个问题:这个结构有两个版本,不同的 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 方法可以轻松找到偏移量。
当我使用这个时,我会将这个答案标记为正确答案。但如果有更好的答案,我可以改变它。我仍然愿意尝试新的想法!
答案 1 :(得分:1)
当你尝试“字符串无效”时发生了什么?它崩溃了?没有正确映射?错过了一些领域?
我过去使用过以下结构......
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct PXUCAMR
{
[MarshalAs(UnmanagedType.I1)]
public sbyte xumrversaocomc01;
// null terminated string?
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 5)]
public string xumrcodfalhac05;
// or just raw data?
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
public sbyte[] xumrcodfalhac05;
}
ByValTStr设置需要CharSet.Ansi。如果xumrcodfalhac05确实是数据而不是字符串,请使用sbyte数组。