11

I am using cgo in a project, and I want to export a function for use. Here's an example of what I want to achieve:

package csplit

import (
    "C"
    "strings"
)

//export Split
/* The Split function takes two C strings, the second of which represents
   a substring to split on, and returns an array of strings. Example:
       Split("1,2", ",") // gives ["1", "2"]
*/
func Split(original *C.char, split *C.char) []*C.char {
        goResult := strings.Split(C.GoString(original), C.GoString(split))
        cResult := make([]*C.char, len(goResult))

        for idx, substring := range goResult {
                cResult[idx] = C.CString(substring)
        }

        return cResult
}

The problem is that the return type is Go allocated data, and not moved into the C heap. This panics with: runtime error: cgo result has Go pointer

1 Answer 1

15

You're returning a Go slice which is allocated in Go, and is a different structure than a C array. You need to allocate an array in C:

//export Split
func Split(original *C.char, split *C.char) **C.char {
    goResult := strings.Split(C.GoString(original), C.GoString(split))
    cArray := C.malloc(C.size_t(len(goResult)) * C.size_t(unsafe.Sizeof(uintptr(0))))

    // convert the C array to a Go Array so we can index it
    a := unsafe.Slice((**C.char)(cArray), len(goResult))

    for idx, substring := range goResult {
        a[idx] = C.CString(substring)
    }

    return (**C.char)(cArray)
}
Sign up to request clarification or add additional context in comments.

6 Comments

ah, thank you. I believe that allocating the C array first may be the trick. (will accept once I test it out for my use case, or add more details to the question if necessary)
@haiqus: sorry, I made a mistake typing this out, and should have included a sizeof in the malloc (I was thinking char instead of char* which would have been obvious had I not omitted the sizeof). I revised it to show the proper malloc size.
I'm late to the party but what does (*[1<<30 - 1]*C.char) mean?
@MikeSchinkel, yes now you would use unsafe.Slice.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.