On Thu, Aug 29, 2019 at 5:15 PM George Hartzell <hartz...@alerce.com> wrote: > > Quick summary, I'm trying to understand the Go structures that cgo > gives me, how they map back onto the C structures and why a Go struct > that doesn't quite match the cgo output seems to work anyway. > > I've called out two explicit questions down below. > > --- > > The Linux kernel provides a character device interface to I2C devices, > and the [i2c-tools] package provides a C library with "convenient" > access functions. > > I'm working on a Go library for the kernel interface on a Raspberry > Pi, because I need it for a project *and* as an etude [so please, > don't do too much of my "homework" for me...;)] > > While digging around for prior art, I found a [partial implementation > by tetsu-koba][tetsu-koba]. Starting from that, I have working bits > to talk to devices via the I2C versions of the commands. > > My next step was to implement the [i2c-tools] SMBus functions. That > requires Go versions of the two C structures that they use. A bit of > research into creating the mapping led to using `cgo -godefs`. Along > the way, I stumbled on a [partial implementation of the SMBus > bits][brandonagr-smbus] by brandon...@gmail.com. > > I ended up with this cgo input file: > > ```go > package main > > /* > #include <stdio.h> > #include <linux/i2c.h> > #include <linux/i2c-dev.h> > */ > import "C" > > type I2CMsg C.struct_i2c_msg > > const Sizeof_I2CMsg = C.sizeof_struct_i2c_msg > > type I2CSMBusIoctlData C.struct_i2c_smbus_ioctl_data > > const Sizeof_I2CSMBusIoctlData = C.sizeof_struct_i2c_smbus_ioctl_data > > type Blort C.struct_blort > > type I2CSMBusData C.union_i2c_smbus_data > > const Sizeof_I2CSMBusData = C.sizeof_union_i2c_smbus_data > ``` > > It generates this output: > > ```go > // Code generated by cmd/cgo -godefs; DO NOT EDIT. > // cgo -godefs foo.go > > package main > > type I2CMsg struct { > Addr uint16 > Flags uint16 > Len uint16 > Buf *uint8 > } > > const Sizeof_I2CMsg = 0xc > > type I2CSMBusIoctlData struct { > Write uint8 > Command uint8 > Size uint32 > Data *[34]byte > } > > const Sizeof_I2CSMBusIoctlData = 0xc > > type Blort struct{} > > type I2CSMBusData [34]byte > > const Sizeof_I2CSMBusData = 0x22 > ``` > > @brandonagr ended up with something that's different for his version > of the i2c_smbus_ioctl_data struct: > > ```go > type i2c_smbus_ioctl_data struct { > read_write uint8 > command uint8 > size int > data *uint8 > } > ``` > > but I can see how it's the same "shape". > > ## Question #1 > > On the *other hand, @tetsu-koba's version of the i2c_msg struct: > > ```go > type i2c_msg struct { > addr uint16 > flags uint16 > len uint16 > __padding uint16 > buf uintptr > } > ``` > > seems to be fundamentally different from the `cgo -godefs` version: > > ```go > type I2CMsg struct { > Addr uint16 > Flags uint16 > Len uint16 > Buf *uint8 > } > ``` > > Before I figured out how to use `cgo -godefs`, I rationalized > @tetsu-koba's struct with the explanation that the `buf` pointer was > being padded out to a 32-bit boundary and was comforted by the fact > that it seems to work (I can use it to talk to e.g. an MCP9808 > temperature sensor). > > But, the `cgo -godefs` output seems to be a different shape, I don't > see how the Buf field ends up in the right place. I haven't tried > *using* it yet, I'd like to understand the why before I comfort myself > with a "seems to work, onward...". Left to my own devices I thought > about trying to get at the assembly language output for the various > structs and seeing what was going on, but that seemed to be One Yak > Too Far. > > Can anyone explain [or a big big clue] what's going on? Is one right > and the other wrong? Are both somehow correct? > > ## Question #2 > > While I'm on this topic, I notice that `cgo -godefs` converted the > struct/field names to Go camel case versions (and stripped the "read_" > prefix from one). But, both @tetsu-koba and @brandonagr stuck with > the C struct names. I've noticed that various go libaries that refer > to kernel data structures (e.g. constants/#defines) don't rename them > in Go style. > > What is the accepted practice in this situation?
This is not a helpful answer but I want to say that using "cgo -godefs" in this way is not supported. You're welcome to use it but it may well break in the future. The "-godefs" option is specifically for generating files used in the syscall and golang.org/x/sys packages, it's not intended for general use. We instead recommend using import "C" and using cgo in the usual way as described at https://golang.org/cmd/cgo/ and https://blog.golang.org/c-go-cgo . Ian -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAOyqgcUnTxnzOAJLpnDYk130idKxBD7A1shCxsUchsxLuoAc1Q%40mail.gmail.com.