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

Cannot use `func` as a field name in a C struct. #41968

Closed
chewxy opened this issue Oct 14, 2020 · 3 comments
Closed

Cannot use `func` as a field name in a C struct. #41968

chewxy opened this issue Oct 14, 2020 · 3 comments

Comments

@chewxy
Copy link

@chewxy chewxy commented Oct 14, 2020

What version of Go are you using (go version)?

$ go version
go version go1.14.2 linux/amd64

Does this issue reproduce with the latest release?

Will try later when I have access to a machine with gvm

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build918375297=/tmp/go-build -gno-record-gcc-switches"

What did you do?

I am adding CUDA 11 support for the CUDA library. This means using cgo. One of the structs is defined as follows:

typedef struct CUDA_KERNEL_NODE_PARAMS_st {
	CUfunction func;
	unsigned int gridDimX;
	unsigned int gridDimY;
	unsigned int gridDimZ;
	unsigned int blockDimX;
	unsigned int blockDimY;
	unsigned int blockDimZ;
	unsigned int sharedMemBytes;
	void** kernelParams;
	void** extra;
} CUDA_KERNEL_NODE_PARAMS;

This struct needs to be passed into a function call.

I am unable to set the field .func. I have tried with a literal:

return C.CUDA_KERNEL_NODE_PARAMS {
		func: p.Func.fn,
		gridDimX: p.GridDimX,
		gridDimY: p.GridDimY,
		gridDimZ: p.GridDimZ,
		blockDimX: p.BlockDimX,
		blockDimY: p.BlockDimY,
		blockDimZ: p.BlockDimZ,
		sharedMemBytes: p.SharedMemBytes,
	}

I have tried it as a selector:

retVal := C.CUDA_KERNEL_NODE_PARAMS {
		gridDimX: p.GridDimX,
		gridDimY: p.GridDimY,
		gridDimZ: p.GridDimZ,
		blockDimX: p.BlockDimX,
		blockDimY: p.BlockDimY,
		blockDimZ: p.BlockDimZ,
		sharedMemBytes: p.SharedMemBytes,
	}
retVal.func = p.Func.fn

What did you expect to see?

No parsing errors

What did you see instead?

For the first case I got:

 expected '(', found ':'

For the second case I got:

./params.go:28:9: expected selector or type assertion, found 'func'

Look, I understand that this is a parsing error. I also understand that Go's goal is to have a one-pass parser. Having to check if we're in a C.XXX context will make it two passes. I have no suggestions.

Workaround

Right now I have a terrible workaround: the struct creation is a cgo function that I call, passing in all the correct values. This is not ideal clearly. The whole point of using CUDA is to speed up computation, and if I have to call cgo repeatedly then that's not great. Especially in this case, where the compiler's just allocating a data structure and populating with values.

@chewxy
Copy link
Author

@chewxy chewxy commented Oct 14, 2020

@noxer suggested another workaround that I hadn't thought of: anonymous struct fields:

return C.CUDA_KERNEL_NODE_PARAMS {
		p.Func.fn,
		p.GridDimX,
		p.GridDimY,
		p.GridDimZ,
		p.BlockDimX,
		p.BlockDimY,
		p.BlockDimZ,
		p.SharedMemBytes,
		nil,
		nil,
	}

It's a nice workaround that does what I had originally intended. But maybe we should look into the whole func-as-a-keyword thing?

@rsc
Copy link
Contributor

@rsc rsc commented Oct 14, 2020

go doc cmd/cgo says:

Go references to C

Within the Go file, C's struct field names that are keywords in Go can be
accessed by prefixing them with an underscore: if x points at a C struct
with a field named "type", x._type accesses the field.

So in this case the field can be referred to as _func, not func.

There is no need to "look into the whole func-as-a-keyword thing".

@rsc rsc closed this Oct 14, 2020
@chewxy
Copy link
Author

@chewxy chewxy commented Oct 14, 2020

Hah serves me right for not RTFMing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants
You can’t perform that action at this time.