c - 如何将 Go 绑定(bind)建模为使用 union 的 C 结构?

标签 c go unions api-design cgo

我目前正在写一个 Go wrapper对于 libfreefare . libfreefare 的 API 包含以下功能:

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);

包装这样一个函数的理想解决方案是什么?如果 struct mifare_desfire_file_settings 不包含任何 union ,我的包装器可能看起来像这样:

type DESFireFileSettings struct {
    // all fields exported, no methods
}

func (t DESFireTag) FileSettings(fileNo byte) (DESFireFileSettings, error)

我应该如何进行?

最佳答案

您需要考虑如何更新 union 中的字段。显然,您不能让用户在未经验证的情况下这样做。他们可以进行不一致的更新。考虑做这样的事情:

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
}

关于c - 如何将 Go 绑定(bind)建模为使用 union 的 C 结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22888001/

相关文章:

go - 使用 Golang 启动 D-Bus 服务

go - 使用模块时在工作区中制作 VSCode 安装包

c - C99 Keil MDK5 中的匿名结构、 union

c++ - 关于C++中 vector 、 union 和指针的问题

c++ - C++11 是否允许非匿名 union 包含静态数据成员?

c - 在 C 中使用 FFTW 求解泊松方程时失去径向对称性

java - 如何将c toHex方法转换为java

c - 如何概括我的代码

go - Go 云中的状态是如何处理的?

c++ - 我需要创建一个非常大的位/ bool 值数组。我将如何在 C/C++ 中执行此操作?