Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/cgo: cgo treats typedef and struct as different types #7786

Closed
gopherbot opened this issue Apr 15, 2014 · 11 comments

Comments

@gopherbot
Copy link

commented Apr 15, 2014

by Guxianjie:

What does 'go version' print?
go version devel +4c6d48b65d66 Tue Apr 15 08:46:21 2014 +0200 freebsd/amd64

What steps reproduce the problem?

1. cat > usb.go <<EOF
package usb

// #cgo LDFLAGS: -lusb
// #include <libusb.h>
import "C"

type Context struct {
        ctx  *C.libusb_context
        done chan struct{}
}

func (c *Context) Close() error {
        close(c.done)
        if c.ctx != nil {
                C.libusb_exit(c.ctx)
        }
        c.ctx = nil
        return nil
}
EOF

2. go build usb.go

What happened?
$go build
# command-line-arguments
./usb.go:15: cannot use c.ctx (type *C.libusb_context) as type *[0]byte in argument to
_Cfunc_libusb_exit

What should have happened instead?
$grep libusb_exit libusb.h
void    libusb_exit(struct libusb_context *ctx);

go 1.2.1 works.

code should be compiled ok.

tested on freebsd 11 current with clang.

Attachments:

  1. usb.go (325 bytes)
@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

commented Apr 15, 2014

Comment 1:

Just to be clear, you're saying that Go 1.2.1 works when using the same OS and compiler?
Can you try to make a standalone test case that does not require libusb.h?

Labels changed: added repo-main, release-go1.3maybe.

@gopherbot

This comment has been minimized.

Copy link
Author

commented Apr 16, 2014

Comment 2 by Guxianjie:

Yes. On FreeBSD 11 go "1.2.1 freebsd/amd64" works.
I updated the test case.

Attachments:

  1. usb.go (406 bytes)
@davecheney

This comment has been minimized.

Copy link
Contributor

commented Apr 16, 2014

Comment 3:

Confirmed. This is what I see using clang on linux/amd64
lucky(~/src/usb) % go build -x
WORK=/tmp/go-build477308532
mkdir -p $WORK/usb/_obj/
mkdir -p $WORK/
cd /home/dfc/src/usb
CGO_LDFLAGS="-g" "-O2" /home/dfc/go/pkg/tool/linux_amd64/cgo -objdir $WORK/usb/_obj/ --
-I $WORK/usb/_obj/ usb.go
/home/dfc/go/pkg/tool/linux_amd64/6c -F -V -w -trimpath $WORK -I $WORK/usb/_obj/ -I
/home/dfc/go/pkg/linux_amd64 -o $WORK/usb/_obj/_cgo_defun.6 -D GOOS_linux -D
GOARCH_amd64 $WORK/usb/_obj/_cgo_defun.c
clang -I . -fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments
-fmessage-length=0 -print-libgcc-file-name
clang -I . -fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments
-fmessage-length=0 -I $WORK/usb/_obj/ -g -O2 -o $WORK/usb/_obj/_cgo_main.o -c
$WORK/usb/_obj/_cgo_main.c
clang -I . -fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments
-fmessage-length=0 -I $WORK/usb/_obj/ -g -O2 -o $WORK/usb/_obj/_cgo_export.o -c
$WORK/usb/_obj/_cgo_export.c
clang -I . -fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments
-fmessage-length=0 -I $WORK/usb/_obj/ -g -O2 -o $WORK/usb/_obj/usb.cgo2.o -c
$WORK/usb/_obj/usb.cgo2.c
clang -I . -fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments
-fmessage-length=0 -o $WORK/usb/_obj/_cgo_.o $WORK/usb/_obj/_cgo_main.o
$WORK/usb/_obj/_cgo_export.o $WORK/usb/_obj/usb.cgo2.o -g -O2
/home/dfc/go/pkg/tool/linux_amd64/cgo -objdir $WORK/usb/_obj/ -dynimport
$WORK/usb/_obj/_cgo_.o -dynout $WORK/usb/_obj/_cgo_import.c
/home/dfc/go/pkg/tool/linux_amd64/6c -F -V -w -trimpath $WORK -I $WORK/usb/_obj/ -I
/home/dfc/go/pkg/linux_amd64 -o $WORK/usb/_obj/_cgo_import.6 -D GOOS_linux -D
GOARCH_amd64 $WORK/usb/_obj/_cgo_import.c
clang -I . -fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments
-fmessage-length=0 -o $WORK/usb/_obj/_all.o $WORK/usb/_obj/_cgo_export.o
$WORK/usb/_obj/usb.cgo2.o -g -O2 -Wl,-r -nostdlib
/usr/lib/gcc/x86_64-linux-gnu/4.8/libgcc.a
/home/dfc/go/pkg/tool/linux_amd64/6g -o $WORK/usb.a -trimpath $WORK -p usb -D
_/home/dfc/src/usb -I $WORK -pack $WORK/usb/_obj/_cgo_gotypes.go
$WORK/usb/_obj/usb.cgo1.go
# usb
./usb.go:16[/tmp/go-build477308532/usb/_obj/usb.cgo1.go:18]: cannot use c.ctx (type
*_Ctype_libusb_context) as type *[0]byte in argument to _Cfunc_libusb_exit
It's probably something clang is doing wrong, this isn't the first time.

Status changed to Accepted.

@orofarne

This comment has been minimized.

Copy link

commented Apr 24, 2014

Comment 4:

Have a project, that fails too with 1.3: https://github.com/orofarne/go-mapnik With gcc,
not clang. Works with 1.2.1.
.....
./mapnik.go:74: cannot use p.p (type *[0]byte) as type *C.mapnik_projection_t in
argument to _Cfunc_mapnik_projection_free
./mapnik.go:80: cannot use p.p (type *[0]byte) as type *C.mapnik_projection_t in
argument to _Cfunc_mapnik_projection_forward
./mapnik.go:90: cannot use _Cfunc_mapnik_map(C.uint(width), C.uint(height)) (type
*C.mapnik_map_t) as type *[0]byte in field value
.....
But I can't to reduce problem to minimal example.
@slimsag

This comment has been minimized.

Copy link

commented Apr 24, 2014

Comment 5:

I can also confirm this issue moving from 1.2.1 to 1.3 (see
https://code.google.com/p/azul3d/issues/detail?id=50).
...
../../azul3d.org/v0/chippy/wrappers/x11/glx.go:93: cannot use d.voidPtr() (type
*[0]byte) as type *C.Display in argument to _Cfunc_glXCreateNewContext
../../azul3d.org/v0/chippy/wrappers/x11/glx.go:105: cannot use d.voidPtr() (type
*[0]byte) as type *C.Display in argument to _Cfunc_glXDestroyContext
...
@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

commented Apr 24, 2014

Comment 6:

Labels changed: added release-go1.3, removed release-go1.3maybe.

@minux

This comment has been minimized.

Copy link
Member

commented Apr 28, 2014

Comment 7:

this new behavior is introduced by https://golang.org/cl/76450043
@rsc

This comment has been minimized.

Copy link
Contributor

commented May 9, 2014

Comment 8:

I think we should try to make this work, although I am not sure how. Here is the
simplified case:
package usb
// struct libusb_context;
// typedef struct libusb_context libusb_context;
// void libusb_exit(struct libusb_context *ctx) {};
import "C"
type Context struct {
        ctx  *C.libusb_context
        done chan struct{}
}
func (c *Context) Close() error {
        close(c.done)
        if c.ctx != nil {
                C.libusb_exit(c.ctx)
        }
        c.ctx = nil
        return nil
}
The problem is that c.txt is a *C.libusb_context but libusb_exit is defined to take a
*C.struct_libusb_context. One is using the typedef name and one is using the struct name
directly. Cgo treats those as different. We've had heuristics in the past to try to
merge them but maybe they were removed or maybe they never worked, and the [0]byte bug
was keeping things working incorrectly.
@gopherbot

This comment has been minimized.

Copy link
Author

commented May 28, 2014

Comment 9:

CL https://golang.org/cl/98580046 mentions this issue.
@rsc

This comment has been minimized.

Copy link
Contributor

commented May 28, 2014

Comment 10:

Owner changed to @rsc.

Status changed to Started.

@rsc

This comment has been minimized.

Copy link
Contributor

commented May 28, 2014

Comment 11:

This issue was closed by revision 0782ee3.

Status changed to Fixed.

@rsc rsc added this to the Go1.3 milestone Apr 14, 2015

@rsc rsc removed the release-go1.3 label Apr 14, 2015

@golang golang locked and limited conversation to collaborators Jun 25, 2016

wheatman added a commit to wheatman/go-akaros that referenced this issue Jun 25, 2018
cmd/cgo: given typedef struct S T, make C.T and C.struct_S interchang…
…eable

For incomplete struct S, C.T and C.struct_S were interchangeable in Go 1.2
and earlier, because all incomplete types were interchangeable
(even C.struct_S1 and C.struct_S2).

CL 76450043, which fixed issue 7409, made different incomplete types
different from Go's point of view, so that they were no longer completely
interchangeable.

However, imprecision about C.T and C.struct_S - really the same
underlying C type - is the one behavior enabled by the bug that
is most likely to be depended on by existing cgo code.
Explicitly allow it, to keep that code working.

Fixes golang#7786.

LGTM=iant, r
R=golang-codereviews, iant, r
CC=golang-codereviews
https://golang.org/cl/98580046

This issue was closed.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
7 participants
You can’t perform that action at this time.