Преобразование строки Go в строку C без CGo

Я пытаюсь вызвать некоторые ioctl из Go, и некоторые из них принимают строки C в качестве параметров. Например, в С:

/* When the user asks to bind a message name to an interface, they use: */
struct kbus_bind_request {
    __u32 is_replier;   /* are we a replier? */
    __u32 name_len;
    char *name;
};

extern int kbus_ksock_bind(kbus_ksock_t         ksock,
                           const char          *name,
                           uint32_t             is_replier)
{
  int   rv;
  kbus_bind_request_t   bind_request;

  bind_request.name = (char *) name;
  bind_request.name_len = strlen(name);
  bind_request.is_replier = is_replier;

  rv = ioctl(ksock, KBUS_IOC_BIND, &bind_request);
  if (rv < 0)
    return -errno;
  else
    return rv;
}

Я преобразовал структуру в структуру Go следующим образом:

type kbus_bind_request struct {
    is_replier uint32 /* are we a replier? */
    name_len   uint32
    name       unsafe.Pointer // char*
}

Теперь, как мне преобразовать Go string в строку C, хранящуюся в unsafe.Pointer? Я не хочу использовать CGo, так как я занимаюсь кросс-компиляцией, и это усложняет задачу.


person Timmmm    schedule 02.08.2016    source источник


Ответы (1)


Ах, нашел ответ (ну, что-то, что все равно компилируется). Сначала приведите к []byte, затем возьмите адрес первого элемента:

func int_bind(ksock int, name string, is_replier uint32) int {

    bind_request := &kbus_bind_request{}

    s := []byte(name)

    bind_request.name = unsafe.Pointer(&s[0])
    bind_request.name_len = uint32(len(s))
    bind_request.is_replier = is_replier

    rv := ioctl(ksock, KBUS_IOC_BIND, unsafe.Pointer(bind_request))

    if rv != 0 {
        return -int(rv)
    }
    return 0
}
person Timmmm    schedule 02.08.2016
comment
Обычно можно сделать поле Name *byte, а не unsafe.Pointer. Найдите примеры в пакете syscall, например: golang.org/pkg/syscall/#Iovec - person JimB; 02.08.2016
comment
Ах да, это имеет больше смысла! - person Timmmm; 02.08.2016