On Sat, Mar 13, 2021 at 6:25 AM rmfr <remus.clearwa...@gmail.com> wrote:
>
> Say here is a C api like `ssize_t writev(const struct iovec *iov, int 
> iovcnt)` which the definition of iovec is like below:
>
> ```
> struct iovec {
>      uint8_t   *Base;  /* Base address. */
>      uint64_t Len;    /* Length. */
>  };
> ```
>
> For C api which like `ssize_t write(const void *buf, size_t nbyte)`, the 
> solution would be quite straight forward:
>
> ```
> bs := make([]byte, 1024*1024*512)
> // without extra memory allocation and copying of the whole input byte slice 
> :-D
> rc := C.write(unsafe.Pointer(&bs[0]), C.int(len(bs)))
> ```
>
> But how to call C `writev` style API without extra memory allocation or 
> copying of the whole byte slice vector?
>
> ```
> bsv := make([][]byte, 1024)
> for i := range bsv{
>     bsv[i] = make([]byte, 5*1024*(rand.Intn(i)+1))
> }
> // assuming that allocation of a iovec array is acceptable
> // but allocation and copying of all bsv[x] byte slice member is unacceptable
> //
> iovec := make([]syscall.Iovec, len(bsv))
> for i := range bsv {
>         bs := bsv[i]
>         if len(bs) > 0 {
>             iovec[i].Base = unsafe.Pointer(&bs[0])
>             iovec[i].Len = uint64(len(bs))
>         }
> }
> //
> // rc := C.writev( /* how? :-( */)
> rc := C.writev(unsafe.Pointer(&iovec[0]), C.int(len(iovec))) // Does this 
> code is right and safe?
> ```
>
> Does the code above is right?
>
> I have read cgo's docs carefully, and here is a constraint from 
> https://golang.org/cmd/cgo/#hdr-Passing_pointers:
>
> > Go code may pass a Go pointer to C provided the Go memory to which it 
> > points does not contain any Go pointers.
>
> If the Go memory pointed by `unsafe.Pointer(&iovec[0])` contains pointer 
> which points to these byte slice members of bsv, so it would be a violation 
> of the cgo constraint above. And that means you could not call C `writev` 
> style API without allocation and copying of the whole vector.
>
> Please correct me if I get something wrong. Thanks a lot :-D


I think that everything you wrote is correct.

In some cases you may be able to work around this problem by creating
the byte slices in memory allocated using C.malloc.

Or, in some cases you can use https://golang.org/pkg/net/#Buffers to
get Go to call writev for you.

But I don't think there is any good solution for the general case.

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.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/CAOyqgcXSwKcK36r4XDrr74atqCJRDQUvFEfieLaEy%2B9WaV6zfw%40mail.gmail.com.

Reply via email to