英文:
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 
binarypackage you can iterate through struct members and place them into a[]byte. The[]bytecan then be passed as a packed struct to C functions. (do the opposite to receive packed structs from c functions) 
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论