On Fri, Aug 30, 2019 at 4:57 PM George Hartzell <hartz...@alerce.com> wrote:
>
> Ian Lance Taylor writes:
>  > On Thu, Aug 29, 2019 at 6:26 PM George Hartzell <hartz...@alerce.com> 
> wrote:
>  > [...]
>  > There is another approach, which is to use import "C", and then write code 
> like
>  >
>  > const IoctlConstant = C.IoctlConstant
>  > type GoIoctlType = C.CIoctlType
>  >
>  > and then use those types in code that calls unix.Syscall(SYS_IOCTL,
>  > IoctlConstant, &GoIoctlType{value}).
>
> Hi Ian,
>
> Thank you for the followup^2.
>
> After re-reading all of the things that you'd pointed me at, I'd
> started heading down that road a bit, but am stuck on one thing and
> have a question.
>
> # Where I'm currently stuck
>
> Here's something that compiles and runs:
>
> ```
> package i2c
>
> // #include <linux/i2c.h>
> // #include <linux/i2c-dev.h>
> import "C"
> import "fmt"
>
> func Foo() {
>   im := C.struct_i2c_msg{}
>   buf := [2]byte{}
>
>   im.addr = 0x18
>   im.flags = C.I2C_M_RD
>   im.len = C.__u16(len(buf))
>   // im.buf = &buf[0]
>   fmt.Println(im)
> }
> ````
>
> The original C structure is defined like so (w/ comments, #defines elided):
>
> ```
> struct i2c_msg {
>   __u16 addr; /* slave address      */
>   __u16 flags;
>   __u16 len;    /* msg length       */
>   __u8 *buf;    /* pointer to msg data      */
> };
> ```
>
> The other approaches that I cribbed supplied the buffer by declaring a
> byte slice and taking the address of the first element. If I uncomment
> line 15 in the above, I get
>
> ```
> i2c/i2c.go:15:9: cannot use &buf[0] (type *byte) as type *_Ctype_uchar
> in assignment
> ```
>
> I can't come up with any cast that makes the compiler happy.

im.buf = (*C.uchar)(unsafe.Pointer(&buf[0]))


> I'm also
> unsure whether that line runs afoul of this commandment: *Go code may
> not store a Go pointer in C memory* from https://golang.org/cmd/cgo/.

There is no C memory here as yet.  That code will be OK if you pass
&im to unix.Syscall.  But it will not be OK if you pass &im to
C.ioctl, as that would violate this rule from
https://golang.org/cmd/cgo: "Go code may pass a Go pointer to C
provided the Go memory to which it points does not contain any Go
pointers."  In this case the Go pointer &im would contain the Go
pointer &buf[0].  But that rule applies to calling cgo functions; it
does not apply to calling unix.Syscall.


> Perhaps I should be allocating that memory myself with a call to
> `C.malloc` or ???

That would also work, and be safe.


> # The question
>
> If I leave out the buf bit and build it, I end with a dynamically
> linked executable, e.g.
>
> ```
> pi@raspberrypi:~/temper/go/cgo-normal-way $ ldd dummy
>         linux-vdso.so.1 (0x7ef23000)
>         /usr/lib/arm-linux-gnueabihf/libarmmem-${PLATFORM}.so => 
> /usr/lib/arm-linux-gnueabihf/libarmmem-v7l.so (0x76f14000)
>         libpthread.so.0 => /lib/arm-linux-gnueabihf/libpthread.so.0 
> (0x76ed3000)
>         libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0x76d85000)
>         /lib/ld-linux-armhf.so.3 (0x76f29000)
> ```
>
> While this is an personal homework problem, I'm also heading towards
> building an application and one of the advantages of using Go is the
> statically compiled binary.  After your initial comment, I'd thought
> perhaps I'd just end up using some cgo magic for the types and structs
> but I'd still end up with a static binary.  That doesn't seem to be
> the case.

OK, that is true.  Since your program will be using cgo, even though
you aren't calling any C functions, it will be dynamically linked by
default.  You could try using "go build -ldflags=-extldflags=-static".
I don't know whether it will work.


> If I go back mimicking the approach used in the x/sys libraries (cgo
> -godefs), what particular "private" behavior am I depending on?  Is it
> the ability to use `cgo -godefs` to figure out a Go equivalent for the
> C data structures, or is it counting on the
> ``uintptr(unsafe.Pointer(...))` to do the right thing, or something
> else?

It is "cgo -godefs".  That is not supported for any use other than
generating the files used by the syscall and runtime packages.  It may
work for you today but there is no guarantee that it will continue to
work.

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/CAOyqgcW0P3581nzvkW94GqQT5hJY6zMnpru-C2Uau78XorK3iw%40mail.gmail.com.

Reply via email to