英文:
How to model Go bindings to C structs that use unions?
问题
我目前正在为libfreefare编写一个Go封装器,libfreefare的API包含以下函数:
type mifare_desfire_file_settings struct {
file_type uint8
communication_settings uint8
access_rights uint16
settings struct {
standard_file struct {
file_size uint32
}
value_file struct {
lower_limit int32
upper_limit int32
limited_credit_value int32
limited_credit_enabled uint8
}
linear_record_file struct {
record_size uint32
max_number_of_records uint32
current_number_of_records uint32
}
}
}
func mifare_desfire_get_file_settings(tag MifareTag, file_no uint8, settings *mifare_desfire_file_settings) int
如果struct mifare_desfire_file_settings
不包含任何联合体,我的封装器可能会像这样:
type DESFireFileSettings struct {
// 所有字段都是公开的,没有方法
}
func (t DESFireTag) FileSettings(fileNo byte) (DESFireFileSettings, error)
你应该如何继续?
英文:
I'm currently writing a Go wrapper for the libfreefare. The API of the libfreefare contains the following function:
struct mifare_desfire_file_settings {
uint8_t file_type;
uint8_t communication_settings;
uint16_t access_rights;
union {
struct {
uint32_t file_size;
} standard_file;
struct {
int32_t lower_limit;
int32_t upper_limit;
int32_t limited_credit_value;
uint8_t limited_credit_enabled;
} value_file;
struct {
uint32_t record_size;
uint32_t max_number_of_records;
uint32_t current_number_of_records;
} linear_record_file;
} settings;
};
int mifare_desfire_get_file_settings (MifareTag tag, uint8_t file_no, struct mifare_desfire_file_settings *settings);
What is the ideomatic solution for wrapping such a function? If the struct mifare_desfire_file_settings
wouldn't contain any unions, my wrapper would probably look like this:
type DESFireFileSettings struct {
// all fields exported, no methods
}
func (t DESFireTag) FileSettings(fileNo byte) (DESFireFileSettings, error)
How should I proceed?
答案1
得分: 2
你需要考虑如何更新联合体中的字段。显然,你不能让用户在没有验证的情况下进行更新,否则可能会导致不一致的更新。考虑像这样做:
package mifare
const (
MDFTStandarDataFile = 0x00
MDFTBackupDataFile = 0x01
MDFTValueFileWithBackup = 0x02
MDFTLinearRecordFileWithBackup = 0x03
MDFTCyclicRecordFileWithBackup = 0x04
)
type StandardFile struct {
FileSize uint32
}
type ValueFile struct {
LowerLimit int32
UpperLimit int32
LimitedCreditValue int32
LimitedCreditEnabled uint8
}
type LinearRecordFile struct {
Record_size uint32
MaxNumberOfRecords uint32
CurrentNumberOfRecords uint32
}
type DESFireFileSettings struct {
FileType uint8
CommunicationSettings uint8
AccessRights uint16
settings struct {
StandardFile
ValueFile
LinearRecordFile
}
}
func (fs *DESFireFileSettings) StandardFile() (StandardFile, error) {
// 如果FileType无效,返回错误
return fs.settings.StandardFile, nil
}
func (fs *DESFireFileSettings) SetStandardFile(standardFile StandardFile) error {
// 如果FileType无效,返回错误
fs.settings.StandardFile = standardFile
return nil
}
func (fs *DESFireFileSettings) ValueFile() (ValueFile, error) {
// 如果FileType无效,返回错误
return fs.settings.ValueFile, nil
}
func (fs *DESFireFileSettings) SetValueFile(valueFile ValueFile) error {
// 如果FileType无效,返回错误
fs.settings.ValueFile = valueFile
return nil
}
func (fs *DESFireFileSettings) LinearRecordFile() (LinearRecordFile, error) {
// 如果FileType无效,返回错误
return fs.settings.LinearRecordFile, nil
}
func (fs *DESFireFileSettings) SetLinearRecordFile(linearRecordFile LinearRecordFile) error {
// 如果FileType无效,返回错误
fs.settings.LinearRecordFile = linearRecordFile
return nil
}
以上是对代码的翻译。
英文:
You need to consider how you would update fields in the union. Obviously, you can't let users do that without validation. They could do inconsistent updates. Consider doing something like this:
package mifare
const (
MDFTStandarDataFile = 0x00
MDFTBackupDataFile = 0x01
MDFTValueFileWithBackup = 0x02
MDFTLinearRecordFileWithBackup = 0x03
MDFTCyclicRecordFileWithBackup = 0x04
)
type StandardFile struct {
FileSize uint32
}
type ValueFile struct {
LowerLimit int32
UpperLimit int32
LimitedCreditValue int32
LimitedCreditEnabled uint8
}
type LinearRecordFile struct {
Record_size uint32
MaxNumberOfRecords uint32
CurrentNumberOfRecords uint32
}
type DESFireFileSettings struct {
FileType uint8
CommunicationSettings uint8
AccessRights uint16
settings struct {
StandardFile
ValueFile
LinearRecordFile
}
}
func (fs *DESFireFileSettings) StandardFile() (StandardFile, error) {
// if not valid for FileType, return error
return fs.settings.StandardFile, nil
}
func (fs *DESFireFileSettings) SetStandardFile(standardFile StandardFile) error {
// if not valid for FileType, return error
fs.settings.StandardFile = standardFile
return nil
}
func (fs *DESFireFileSettings) ValueFile() (ValueFile, error) {
// if not valid for FileType, return error
return fs.settings.ValueFile, nil
}
func (fs *DESFireFileSettings) SetValueFile(valueFile ValueFile) error {
// if not valid for FileType, return error
fs.settings.ValueFile = valueFile
return nil
}
func (fs *DESFireFileSettings) LinearRecordFile() (LinearRecordFile, error) {
// if not valid for FileType, return error
return fs.settings.LinearRecordFile, nil
}
func (fs *DESFireFileSettings) SetLinearRecordFile(linearRecordFile LinearRecordFile) error {
// if not valid for FileType, return error
fs.settings.LinearRecordFile = linearRecordFile
return nil
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论