'panic: runtime error: cgo result has Go pointer

Hello i was recently trying to call a golang function from python code that is printing some division things with for loop.

Full code of recap.go:

package main

import (
    "C"
    "strconv"
)

//export PrintAlg
func PrintAlg(debug bool) string {
    var b200 int = 0
    var b300 int = 0
    var b400 int = 0
    var x string = "A"
    if debug == true {
        // extra
    } else if debug == false {
        for i := 1; i <= 100; i++ {
            if i%4 == 0 && i%3 == 0 {
                b200++
                b300++
                b400++
            } else if i%4 == 0 && !(i%3 == 0) {
                b400++
                b200++
            } else if i%2 == 0 && i%3 == 0 && !(i%4 == 0) {
                b200++
                b300++
            } else if i%3 == 0 && !(i%2 == 0) && !(i%4 == 0) {
                b300++
            } else if i%2 == 0 && !(i%3 == 0) && !(i%4 == 0) {
                b200++
            } else if i%2 == 0 && i%3 == 0 && i%4 == 0 {
                b200++
                b300++
                b400++
            }
        }
        x = strconv.Itoa(b200) + " " + strconv.Itoa(b300) + " " + strconv.Itoa(b400)
    }
    return x
}

func main() {

}


then i tryed to call PrintAlg function with CTYPES (in python code). Then when i ran the python code from cmd, this error occured:

panic: runtime error: cgo result has Go pointer

goroutine 17 [running, locked to thread]:
panic({0x67322a80, 0xc00004a0a0})
        C:/Program Files/Go/src/runtime/panic.go:1147 +0x3a8
runtime.cgoCheckArg(0x67320da0, 0xc00004a090, 0x10, 0x0, {0x6732cc4f, 0x19})
        C:/Program Files/Go/src/runtime/cgocall.go:514 +0x4d8
runtime.cgoCheckResult({0x67320da0, 0xc00004a090})
        C:/Program Files/Go/src/runtime/cgocall.go:630 +0x54
_cgoexp_ba17693967af_PrintAlg(0x108efee9c0)
        _cgo_gotypes.go:39 +0x5a
runtime.cgocallbackg1(0x67315640, 0x0, 0x0)
        C:/Program Files/Go/src/runtime/cgocall.go:306 +0x29a
runtime.cgocallbackg(0x0, 0x0, 0x0)
        C:/Program Files/Go/src/runtime/cgocall.go:232 +0x106
runtime.cgocallbackg(0x67315640, 0x108efee9c0, 0x0)
        <autogenerated>:1 +0x36
runtime.cgocallback(0x0, 0x0, 0x0)
        C:/Program Files/Go/src/runtime/asm_amd64.s:915 +0xd7
runtime.goexit()
        C:/Program Files/Go/src/runtime/asm_amd64.s:1581 +0x1

what can i do for fixing this error?

go


Solution 1:[1]

The Go runtime implementation of a string is

type stringStruct struct {
    str unsafe.Pointer
    len int
}

When you return from your Go PrintAlg function - return x - Go returns a Go memory instance of stringStruct which points to the underlying bytes of the Go string x.

panic: runtime error: cgo result has Go pointer

Read the cgo documentation, especially Passing_pointers, for details.

In Go, write

func PrintAlg(debug bool) *C.char {
    // ...
    return C.CString(x)
}

to return a pointer to an instance of a C string. Free the pointer when no longer needed.



$ go build -buildmode=c-shared -o _recap.so
$ python3 recap.py
50 33 25
$

recap.go:

package main

import (
    "C"
    "strconv"
)

//export PrintAlg
func PrintAlg(debug bool) *C.char {
    var b200 int = 0
    var b300 int = 0
    var b400 int = 0
    var x string = "A"
    if debug == true {
        // extra
    } else if debug == false {
        for i := 1; i <= 100; i++ {
            if i%4 == 0 && i%3 == 0 {
                b200++
                b300++
                b400++
            } else if i%4 == 0 && !(i%3 == 0) {
                b400++
                b200++
            } else if i%2 == 0 && i%3 == 0 && !(i%4 == 0) {
                b200++
                b300++
            } else if i%3 == 0 && !(i%2 == 0) && !(i%4 == 0) {
                b300++
            } else if i%2 == 0 && !(i%3 == 0) && !(i%4 == 0) {
                b200++
            } else if i%2 == 0 && i%3 == 0 && i%4 == 0 {
                b200++
                b300++
                b400++
            }
        }
        x = strconv.Itoa(b200) + " " + strconv.Itoa(b300) + " " + strconv.Itoa(b400)
    }
    return C.CString(x)
}

func main() {}

recap.py:

import ctypes
recap = ctypes.cdll.LoadLibrary('./_recap.so')
printAlg = recap.PrintAlg
printAlg.argtypes = [ctypes.c_bool]
printAlg.restype = ctypes.c_void_p
free = recap.free
free.argtypes = [ctypes.c_void_p]
px = printAlg(False)
x = ctypes.string_at(px).decode('utf-8')
free(px)
print(x)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1