преобразовать массив строк из CGO в GO - PullRequest
0 голосов
/ 26 мая 2020

Могу ли я преобразовать массив строк (char **), возвращенный функцией C (cgo), в Go? Приведенный ниже код компилируется и запускается, но я не могу перемещаться по списку строк.
И я даже не уверен, нарушает ли он правила «прохождения указателей»: https://golang.org/cmd/cgo/ Любые мысли были бы полезны, прошло много лет с тех пор, как я кодировал C! Заранее спасибо!

package main
/*
#include "stdlib.h"

char** getlist ()
{
    char **array = NULL;
    array = (char**)realloc(array, 2*sizeof(*array));
    array[0]="HELLO";
    array[1]="WORLD";
    return array;
}

*/
import "C"

import (
    "log"
    "unsafe"
)

func main() {
    list := C.getlist();
    log.Printf("\n========\n C.getList()=%s", list)
    ulist := unsafe.Pointer(list)
    log.Printf("\n========\nulist=%s", ulist)
}

1 Ответ

0 голосов
/ 26 мая 2020

Чтобы перебрать строки в Go, вам необходимо преобразовать массив в фрагмент Go. Мы можем пропустить выделение здесь и преобразовать его напрямую (в вашем примере длина статически устанавливается равной 2, но на практике у вас, вероятно, будет другой источник для этого размера)

cSlice := (*[1 << 28]*C.char)(unsafe.Pointer(list))[:2:2]

Мы можем перебирать это напрямую, и используйте функцию C.GoString для преобразования строк C. Это безопаснее хранить, поскольку он копирует данные в память Go, но если бы этот фрагмент был исключительно большим, мы могли бы сохранить выделение с таким же небезопасным преобразованием, как указано выше, хотя сначала вам нужно будет найти длину каждой строки.

var slice []string
for _, s := range (*[1 << 28]*C.char)(unsafe.Pointer(list))[:2:2] {
    slice = append(slice, C.GoString(s))
}
...