5

go [][]byte から C **char に変換したいと思います。つまり、C で char double ポインターに変換したいバイト マトリックスが go にあります。

[][]byte を入力として、**char を出力として持つ必要があると仮定してください。

次のような方法で []byte から *char に変換できることはわかっています。

((*C.char)(unsafe.Pointer(&data[0])))

しかし、このケースを 2 次元に拡張することはできないようです。[][]バイトを新しい[]バイトにパックする、かなり手の込んだことを試しました。次に、その []byte を C 関数に送信します。C 関数は、ポインター演算を使用して **char を作成し、新しい []byte の正しい位置を指します。

ただし、この変換により奇妙な動作が発生します。データは数回の反復では正しいのですが、関数呼び出し間で破損しているように見えます。

誰かに何かアイデアがあれば、本当に感謝します。

回答から、文字列ではなく生データを扱っていることを述べることが重要であることがわかります。したがって、ゴーバイトタイプです。したがって、C 文字列ターミネータを追加すると、元のデータが破損します。char のサイズは 1 バイトであるため、C **char を使用しています。そうは言っても、応答に感謝します。受け入れられた回答を自分のニーズに合わせることができました。

4

2 に答える 2

4

テストされていないスケルトン:

func foo(b [][]byte) {
        outer := make([]*C.char, len(b)+1)
        for i, inner := range b {
                outer[i] = C.CString(string(inner))
        }
        C.bar(unsafe.Pointer(&outer[0])) // void bar(**char) {...}
}

編集:完全な例(テスト済み):

package main

/*
#include <stdlib.h>
#include <stdio.h>

void bar(char **a) {
        char *s        ;
        for (;(s = *a++);)
                printf("\"%s\"\n", s);
}
*/
import "C"
import "unsafe"

func foo(b [][]byte) {
        outer := make([]*C.char, len(b)+1)
        for i, inner := range b {
                outer[i] = C.CString(string(inner))
        }
        C.bar((**C.char)(unsafe.Pointer(&outer[0]))) // void bar(**char) {...}
}

func main() {
        foo([][]byte{[]byte("Hello"), []byte("world")})
}

(15:24) jnml@fsc-r550:~/src/tmp/SO/14833531$ go run main.go 
"Hello"
"world"
(15:25) jnml@fsc-r550:~/src/tmp/SO/14833531$ 
于 2013-02-12T13:56:08.290 に答える
3

これは手動で行う必要があります。新しいタイプを割り当て、スライス**C.char内の各要素をループして新しいリストに割り当てる必要があります。これには、反復ごとに正しいサイズでポインター[][]byteをオフセットすることが含まれます。**C.char

これを行うプログラムの例を次に示します。

以下のコメントが示すように、C のchar *ようなものを使用してリストを出力する場合は、入力文字列が NULL で終了していることを確認してください。printf関数を使用して変換するのが理想的C.CString()です。ただし、これはそれらが文字列として扱われることを前提としています。それ以外の場合は、個々のchar *リストの長さを C 関数に渡す方法も提供する必要があります。

package main

/*
#include <stdlib.h>
#include <stdio.h>

void test(char **list, size_t len)
{
    size_t i;

    for (i = 0; i < len; i++) {
        //printf("%ld: %s\n", i, list[i]);
    }
}
*/
import "C"
import "unsafe"

func main() {
    list := [][]byte{
        []byte("foo"),
        []byte("bar"),
        []byte("baz"),
    }

    test(list)
}

func test(list [][]byte) {
    // Determine the size of a pointer on the current system.
    var b *C.char
    ptrSize := unsafe.Sizeof(b)

    // Allocate the char** list.
    ptr := C.malloc(C.size_t(len(list)) * C.size_t(ptrSize))
    defer C.free(ptr)

    // Assign each byte slice to its appropriate offset.
    for i := 0; i < len(list); i++ {
        element := (**C.char)(unsafe.Pointer(uintptr(ptr) + uintptr(i)*ptrSize))
        *element = (*C.char)(unsafe.Pointer(&list[i][0]))
    }

    // Call our C function.
    C.test((**C.char)(ptr), C.size_t(len(list)))
}

出力は次のとおりです。

$ go run charlist.go 
0: foo
1: bar
2: baz
于 2013-02-12T14:05:44.137 に答える