如何对使用联合体的C结构建模以实现Go绑定?

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

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
}

huangapple
  • 本文由 发表于 2014年4月6日 07:03:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/22888001.html
匿名

发表评论

匿名网友

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

确定