C.size_t cgo pointer

2,305 views
Skip to first unread message

serbaut

unread,
Nov 13, 2012, 5:32:11 PM11/13/12
to golan...@googlegroups.com
nvm: as I was writing this I realized y should be uint64

I am having trouble with size_t pointers in cgo:

// void foo(int *x)
// void bar(size_t *y)

var x int32
var y int64

foo((*C.int)(&x)) // works
bar((*C.size_t)(&y)) // error: cannot convert &y (type *int64) to type *_Ctype_size_t

This is on 64 bit linux with gcc (GCC) 4.4.6 20120305 (Red Hat 4.4.6-4)

Should y be of some other type?

minux

unread,
Nov 14, 2012, 2:43:35 AM11/14/12
to serbaut, golan...@googlegroups.com
i think it's better to use uintptr for c type size_t.

also note that you need to first convert &y to unsafe.Pointer type
and then convert that to *C.size_t. Go doesn't allow arbitrary
conversion between pointer types, it must go through unsafe.Pointer.

serbaut

unread,
Nov 14, 2012, 3:23:00 PM11/14/12
to golan...@googlegroups.com, serbaut
Not sure what you mean, the following runs fine with go tip:

package main

// #include <stddef.h>
// void foo(int *x) { *x = 17; }
// void bar(size_t *y) { *y = 4711; }
import "C"
import "fmt"

func main() {
    var x int32
    var y uint64
    C.foo((*C.int)(&x))
    C.bar((*C.size_t)(&y))
    fmt.Println(x, y)
}

bryanturley

unread,
Nov 14, 2012, 3:39:59 PM11/14/12
to golan...@googlegroups.com, serbaut

The problem is int is 32bit on 32bit platforms and will soon be 64bit on 64bit platforms.
uintptr also adjusts it's size based on target arch, which probably the reason size_t was created as well.

serbaut

unread,
Nov 14, 2012, 4:04:12 PM11/14/12
to golan...@googlegroups.com, serbaut
How should I rewrite the code above in that case?

Uli Kunitz

unread,
Nov 15, 2012, 1:40:53 AM11/15/12
to golan...@googlegroups.com, serbaut
I would put that more precise: The language specification defines that uint and int might have 32 bit or 64 bit size whereby int and uint must have the same size.

Actually the size of uint and int will change from 32 bit to 64 bit from 1.0.3 to 1.1 on amd64.

minux

unread,
Nov 15, 2012, 2:28:37 AM11/15/12
to serbaut, golan...@googlegroups.com
On Thu, Nov 15, 2012 at 4:23 AM, serbaut <ser...@gmail.com> wrote:
Not sure what you mean, the following runs fine with go tip:

package main

// #include <stddef.h>
// void foo(int *x) { *x = 17; }
// void bar(size_t *y) { *y = 4711; }
import "C"
import "fmt"

func main() {
    var x int32
    var y uint64
    C.foo((*C.int)(&x))
    C.bar((*C.size_t)(&y))
    fmt.Println(x, y)
}
this runs fine simply because size_t is an alias for uint64 on your system.

in general, size_t should correspond to uintptr, and if you declare y as type uintptr, you
need to use unsafe.Pointer to help converting &y to *C.size_t.

serbaut

unread,
Nov 16, 2012, 3:08:50 PM11/16/12
to golan...@googlegroups.com, serbaut
I dont expect my code to be built on anything else than 64 bit linux but thanks for the explanations!

package main

// #include <stddef.h>
// void foo(int *x) { *x = 17; }
// void bar(size_t *y) { *y = 4711; }
import "C"
import (
    "fmt"
    "unsafe"
)

func main() {
    var x int32
    var y uintptr
    C.foo((*C.int)(&x))
    C.bar((*C.size_t)(unsafe.Pointer(&y)))
    fmt.Println(x, y)
Reply all
Reply to author
Forward
0 new messages