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.

Reply via email to