I am trying to pass 2d array from Go to some C function void foo(in 
**float, out *double). Since I want to have wrapper for this C function, 
I'd like that Go function has definition like func FooWrapper([][]float32) 
[]float64. The easiest but not efficient implementation is allocating all 
memory through C that listed below:

func FooWrapper(values [][]float32) []float64 {
    totalObj := len(values)
    totalParams := len(values[0])
    results := make([]float64, totalObj)

    ptrArrLength := uintptr(totalObj) * cPointerSize
    paramArrLength := uintptr(totalParams) * cFloatSize

    ptr := C.malloc(C.size_t(ptrArrLength + 
paramArrLength*uintptr(totalObj)))
    defer C.free(ptr)

    ptrSlice := unsafe.Slice((**C.float)(ptr), totalObj)
    for i, obj := range values {
        paramArrPtr := (*C.float)(unsafe.Add(ptr, 
ptrArrLength+uintptr(i)*paramArrLength))
        ptrSlice[i] = paramArrPtr

        paramSlice := unsafe.Slice(paramArrPtr, totalParams)
        for j, param := range obj {
            paramSlice[j] = (C.float)(param)
        }
    }

    C.foo((**C.float)(ptr), (*C.double)(&results[0]))

    return results
}

Is that safe implementation? Can I pass pointer of result data? As far as I 
know, this pointer will be pinned because it passed to C function.

But I want to allocate less memory just reusing Go memory, I've learned 
about runtime.Pinner that make pointer pinned until runtime.Pinner.Unpin() 
invocation. 
I tried to write another implementation using pinner:

func FooWrapper(values [][]float32) []float64 {
    length := len(values)
    results := make([]float64, length)

    pinner := runtime.Pinner{}
    defer pinner.Unpin()

    arr := (**C.float)(C.malloc(C.size_t(uintptr(length) * cPointerSize)))
    defer C.free(unsafe.Pointer(arr))
    slice := unsafe.Slice(arr, length)
    for i, v := range values {
        pinner.Pin(&v[0])
        slice[i] = (*C.float)(&v[0])
    }

    C.foo(arr, (*C.double)(&results[0]))

    return results
}

But, unfortunately, this code doesn't work

runtime: pointer 0xc016ecbfc0 to unused region of span 
span.base()=0xc016eca000 span.limit=0xc016ecbfa0 span.state=1
fatal error: found bad pointer in Go heap (incorrect use of unsafe or cgo?)

Do I use runtime.Pinner wrong (as far as I know, I can pin slice data)? Or 
there is another error in this code. Are there some implementations for 
passing 3d (4d and so on) array to C function except for allocatiing and 
copying all data to C memory?

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/82fd0ab7-0fa9-46cb-b752-699877478744n%40googlegroups.com.

Reply via email to