cmd/cgo: cannot create file using cgo function: file name becomes an invalid encoding

Please answer these questions before submitting your issue. Thanks!

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

go1.10.2 linux/amd64

Does this issue reproduce with the latest release?

not sure, didn’t tested with anything above the version I have

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

GOHOSTARCH="amd64"
GOHOSTOS=“linux”

What did you do?

I’m trying to convert a GO program into a shared library to be used on my R script. At first I tested with something simple, I have a function that takes an input path (string) and creates a file on the disk. My problem is that the string with the path becomes something with an invalid encoding, see below:

If possible, provide a recipe for reproducing the error.
A complete runnable program is good.
A link on play.golang.org is best.

This is my function:

import "C"

(...)

//export testWriter
func testWriter(path string) string {

	file, err := os.Create(path)
	if err != nil {
		return "error"
	}
	defer file.Close()

	return path
}

I compile the library with:

go build -o gowriter.so -buildmode=c-shared ./gowriter

And then I run my R script like this:

 Rscript -e 'dyn.load("/home/user/go/src/github.com/user/gowriter.so"); .Call("testWriter", "/home/user/test.txt")'

I also tried running this in a Python program:

from ctypes import *
lib = cdll.LoadLibrary("/home/user/go/src/github.com/prvst/testwriter.so")
lib.testReader("/home/user/test.txt")

And what I get is a file called ` � (invalid encoding) `. That’s literally the file name, including that exclamation symbol you see there.

I added some print functions trying to understand the problem and this is what I get :

fmt.Println(reflect.TypeOf(path))                     # string
fmt.Println(reflect.TypeOf(C.CString(path)))   # *main._Ctype_char
fmt.Println(C.CString(path))                            # 0x559b609e1210

I also tried this without any success:

func testWriter(path *C.char) *C.char {

	file, err := os.Create(C.GoString(path))
	if err != nil {
		return C.CString("error")
	}
	defer file.Close()

	return path
}

What I find curious is that the function ends at the return statement and I can see on the terminal the correct string with the path that was passed to the function.

What did you expect to see?

An empty file on my disk called test.txt

What did you see instead?

An empty file on my disk called � (invalid encoding)

I don’t have specific experience with this, but it sounds to me like it stems from Go’s UTF-8 encoding standard. Maybe use the utf8 c library to parse with?

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.