solved it: //export Eb_TcpSecureStreamCreateListener
func Eb_TcpSecureStreamCreateListener(listenIp string, listenPort int) unsafe.Pointer, retStatus { pmap := &ThreadSafePeerMap{ .... .... } server := Server{ .... .... } server.listener = secConn.NewListener(server.listenAddress, server.ID) //allocate memory on C heap. we send the server address in this pointer //allocated memory is freed in Eb_TcpSecureStreamCloseListener() serverMemAlloc := C.malloc(C.size_t(unsafe.Sizeof(uintptr(0)))) //create array to write the address in the array a := (*[1]*Server)(serverMemAlloc) //save the address in index 0 of the array a[0] = &(*(*Server)(unsafe.Pointer(&server))) return serverMemAlloc, C.Success } and the unsafe.Pointer receiver: //export Eb_TcpSecureStreamCloseListener func Eb_TcpSecureStreamCloseListener(listenerHandle unsafe.Pointer) (retStatus int) { if listenerHandle == nil { return C.BadInput } server := *(*Server)((*[1]*Server)(listenerHandle)[0]) err := server.listener.Close() //freeing listenerHandle regardless of Close() returned status C.free(listenerHandle) if err != nil { return C.Error } return C.Success } thanks, On Tuesday, December 18, 2018 at 5:14:45 PM UTC+2, Ian Lance Taylor wrote: > > On Tue, Dec 18, 2018 at 6:27 AM <eran....@gmail.com <javascript:>> wrote: > > > > I have to projects. One is cgo and one is C application. > > The cgo has a function which needs to return pointer to struct. > > The C app receives this pointer and then calls other function in cgo > with this pointer. > > I build the cgo as shared lib: > > > > go build -o ebsdk.so -buildmode=c-shared > > > > The cgo function is this: > > > > //export Eb_TcpSecureStreamCreateListener > > func Eb_TcpSecureStreamCreateListener(listenIp string, listenPort int) > unsafe.Pointer { > > > > pmap := &ThreadSafePeerMap{ > > peerMap: make(map[string]*Peer, 0), > > Mutex: sync.RWMutex{}, > > } > > > > server := &Server{ > > ID: cert.Subject.CommonName, > > listenAddress: listenIp + ":" + strconv.Itoa(listenPort), > > libSecConn: secConn, > > PeerMap: pmap, > > InboundChannel: make(chan *TcpMessage, channelSize), > > OutgoingChannel: make(chan *TcpMessage, channelSize), > > ClosedConnections: make(chan *TcpMessage, channelSize), > > shutdown: false, > > } > > > > server.listener = secConn.NewListener(server.listenAddress, server.ID) > > > > return unsafe.Pointer(server) > > } > > > > C code calls this cgo function with the returned unsafe.Pointer: > > > > > > func Eb_TcpSecureStreamCloseListener(listenerHandle unsafe.Pointer) > (retStatus int) { > > > > if listenerHandle == nil { > > return C.BadInput > > } > > > > server := *(*Server)(listenerHandle) > > > > err := server.listener.Close() > > if err != nil { > > return C.Error > > } > > > > return C.Success > > } > > > > > > My problem is that Eb_TcpSecureStreamCreateListener() return statement > cause panic: "runtime error: cgo result has Go pointer" > > See https://golang.org/cmd/cgo/#hdr-Passing_pointers . "A Go function > called by C code may not return a Go pointer." > > I'm not sure what to suggest because I'm not sure what you are trying > to do. One approach that works for some programs is to store the > pointer in a Go map that uses integer keys, and return the map key. > Since it looks like the struct can only be used from Go, the Go code > can use the map key to look up the struct. Of course you then need to > know when you can remove the struct from the map so that the garbage > collector can release it. > > Ian > -- 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. For more options, visit https://groups.google.com/d/optout.