将Packed C结构转换为Go结构体时出现问题,通过cgo。

huangapple go评论70阅读模式
英文:

Problem in converting Packed C structs to go structure by cgo

问题

当我们使用#pragma pack (push, 1)对C结构进行打包,并通过cgo转换为Go结构时,转换后的Go结构中有一些字段丢失。

我正在使用的Go版本是:1.16.6 Windows/386

例如,我的C结构如下所示:

#pragma pack (push, 1)
typedef struct _sample_struct
{
	USHORT                   usNo;
	DWORD                    ft;
	DWORD                    fit;
	CHAR                     cID[5];
	CHAR                     cCID[3];
	ULONG                    ulVal;
	ULONG                    ulIn;
	ULONG                    ulCnt;
	ULONG                    ulMax;
	USHORT                   usStat;
	BOOL                     bAlk;
	LPSTRUCT2                lpNNL;
	USHORT                   usNPCU;
	LPSTRUCT4 *              lppP;
	LPSTR                    lpBuff;
	LPUSHORT                 lpusIDS;
	WORD                     usType;
	LPSTR                    lpszCUName;
	ULONG                    ulICnt;
	ULONG                    ulDCnt;
	ULONG                    ulPCnt;
	ULONG                    ulRCnt;
	ULONG                    ulRJCnt;
	ULONG                    ulMin;
} SAMPLESTRUCT, *LPSAMPLESTRUCT;
#pragma pack (pop)

转换为Go后,结构如下所示:

type _Ctype_struct__sample_struct struct {
	usNo		_Ctype_USHORT
	_		[8]byte
	cID		[5]_Ctype_CHAR
	cCID		[3]_Ctype_CHAR
	_		[16]byte
	usStat		_Ctype_USHORT
	bAlk		_Ctype_BOOL
	lpNNL		_Ctype_LPSTRUCT2
	usNPCU		_Ctype_USHORT
	_		[12]byte
	usType		_Ctype_WORD
	lpszCUName	_Ctype_LPSTR
	ulICnt		_Ctype_ULONG
	ulDCnt		_Ctype_ULONG
	ulPCnt		_Ctype_ULONG
	ulRCnt		_Ctype_ULONG
	ulRJCnt		_Ctype_ULONG
	ulMin		_Ctype_ULONG
}

正如我们所看到的,一些字段没有正确转换;相反,它们有“_”。

如果没有#pragma pack行,转换是正确的;然而,我需要进行打包,因为我使用的库对发送到我们应用程序的结构要求进行打包。

有没有解决这个问题的方法?

英文:

When we use #pragma pack (push, 1) to pack the C structure and convert to go structure by cgo, some of the fields are missing in the converted Go structure.

I am using Go version: 1.16.6 Windows/386

For example, my C struct is like this:

#pragma pack (push, 1)
typedef struct _sample_struct
{
	USHORT                   usNo;
	DWORD                    ft;
	DWORD                    fit;
	CHAR                     cID[5];
	CHAR                     cCID[3];
	ULONG                    ulVal;
	ULONG                    ulIn;
	ULONG                    ulCnt;
	ULONG                    ulMax;
	USHORT                   usStat;
	BOOL                     bAlk;
	LPSTRUCT2                lpNNL;
	USHORT                   usNPCU;
	LPSTRUCT4 *              lppP;
	LPSTR                    lpBuff;
	LPUSHORT                 lpusIDS;
	WORD                     usType;
	LPSTR                    lpszCUName;
	ULONG                    ulICnt;
	ULONG                    ulDCnt;
	ULONG                    ulPCnt;
	ULONG                    ulRCnt;
	ULONG                    ulRJCnt;
	ULONG                    ulMin;
} SAMPLESTRUCT, *LPSAMPLESTRUCT;
#pragma pack (pop)

Converted to Go, the structure looks like below:

type _Ctype_struct__sample_struct struct {
	usNo		_Ctype_USHORT
	_		[8]byte
	cID		[5]_Ctype_CHAR
	cCID		[3]_Ctype_CHAR
	_		[16]byte
	usStat		_Ctype_USHORT
	bAlk		_Ctype_BOOL
	lpNNL		_Ctype_LPSTRUCT2
	usNPCU		_Ctype_USHORT
	_		[12]byte
	usType		_Ctype_WORD
	lpszCUName	_Ctype_LPSTR
	ulICnt		_Ctype_ULONG
	ulDCnt		_Ctype_ULONG
	ulPCnt		_Ctype_ULONG
	ulRCnt		_Ctype_ULONG
	ulRJCnt		_Ctype_ULONG
	ulMin		_Ctype_ULONG
}

As we can see, some of the fields are not converted properly; instead, it has "_".**

Conversion is correct without the #pragma pack lines; however, I need packing in place because the library that I use imposes packing for the structures that are sent to our application.

Is there any solution to this problem?

答案1

得分: 1

我实际上在这个问题上写了一篇完整的博客文章:https://medium.com/@liamkelly17/working-with-packed-c-structs-in-cgo-224a0a3b708b

简要说明如下:

  • 查看Go的GitHub维基页面,在cgo部分他们明确提到cgo不会对结构体进行打包
  • 你可以很容易地自己打包结构体,类似于将结构体编码为JSON然后发送。通过使用binary包,你可以迭代结构体成员并将它们放入[]byte中。然后可以将[]byte作为打包的结构体传递给C函数(从C函数接收打包的结构体则相反操作)。
英文:

I actually wrote a whole blog post on this: https://medium.com/@liamkelly17/working-with-packed-c-structs-in-cgo-224a0a3b708b

The quick notes are:

  • Look at the Go wiki page on GitHub, in the cgo section they explicitly mention cgo will not pack structs
  • You can very easily pack the structs yourself in a similar to encoding a struct to JSON before sending it. By using the binary package you can iterate through struct members and place them into a []byte. The []byte can then be passed as a packed struct to C functions. (do the opposite to receive packed structs from c functions)

huangapple
  • 本文由 发表于 2022年7月5日 16:28:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/72866267.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定