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.

Reply via email to