2016-08-02 2 views
1

J'essaie d'appeler certains ioctls de Go, et certains d'entre eux prennent des chaînes C comme paramètres. Par exemple, dans C:Convertir la chaîne Go en chaîne C sans CGo

/* 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; 
} 

Je converti struct à une struc Go comme ceci:

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

Maintenant, comment puis-je convertir un Go string à une chaîne de C stockée dans un unsafe.Pointer? Je ne veux pas utiliser CGo car je compile plusieurs fois et ça fait mal.

Répondre

0

Ah trouvé la réponse (enfin quelque chose qui compile quand même). Tout d'abord coulé à []byte, puis prendre l'adresse du premier élément:

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 
} 
+1

On pourrait normalement faire le champ '' un NAME' * byte' plutôt qu'un 'unsafe.Pointer'. Recherchez des exemples dans le paquet syscall, comme: https://golang.org/pkg/syscall/#Iovec – JimB

+0

Ah oui cela a plus de sens! – Timmmm