2013-02-12 2 views
4

go [] [] 바이트에서 C ** char로 변환하고 싶습니다. 즉, C에서 char double 포인터로 변환하고자하는 바이트 행렬을 가지고 있습니다.에 변환하는 방법은 [] [byte]에서 ** char로 변환 **

입력으로 [] [] 바이트를 가져야하고 산출.

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

그러나 두 번째 차원으로이 사건을 확장하는 것이 가능하지 않는 것 :

나는 * 같은 것을 수행하여 문자 []를 바이트로 변환 할 수 있습니다 알고 있습니다. 나는 [[] [] 바이트를 새로운 [] 바이트로 팩하는 꽤 정교한 것을 시도했다. 그런 다음 [] 바이트를 포인터 연산을 사용하여 올바른 위치에있는 [] 바이트를 가리키는 ** 문자를 만드는 C 함수에 보냅니다.

이 변환은 내 데이터가 몇 번의 반복에 대해 정확하지만 겉으로는 함수 호출간에 손상되는 이상한 동작을 제공합니다.

누구나 아이디어가 있다면 정말 고맙겠습니다.

응답에서 볼 때, 원시 데이터가 아닌 문자열로 작업하는 것이 중요하다는 것을 알 수 있습니다. 따라서 go 바이트 유형입니다. 따라서 C 문자열 터미네이터가 추가되면 원래 데이터가 손상됩니다. char는 크기가 1 바이트이므로 C ** char 만 사용하고 있습니다. 즉, 응답 주셔서 감사합니다. 나는 내 요구에 맞는 대답을 받아 들일 수 있었다.

답변

2

이 수동으로 수행해야합니다. 새 **C.char 유형을 할당하고 [][]byte 슬라이스의 각 요소를 반복하여 새 목록에 할당해야합니다. 여기에는 **C.char 포인터를 각 반복마다 올바른 크기만큼 오프셋하는 작업이 포함됩니다.

다음은이 작업을 수행하는 예제 프로그램입니다.

아래의 의견에서 C에서 printf과 같은 것을 사용하여 char * 목록을 인쇄하려면 입력 문자열이 NULL로 끝났는지 확인하십시오. 이상적으로는 C.CString() 기능을 사용하여 변환하는 것이 좋습니다. 이것은 그들이 문자열로 취급되어야한다고 가정합니다. 그렇지 않으면 각 char * 목록의 길이를 C 함수에 전달하는 방법을 제공해야 할 수도 있습니다.

$ go run charlist.go 
0: foo 
1: bar 
2: baz 
+1

C 문자열에 널 문자가 있다고 생각하지 않습니까? 귀하의 사례가 효과가 있었지만 운이 좋았다고 생각됩니다! –

+0

아주 좋아요. '* element = (* C.char) (unsafe.Pointer (& list [i] [0]))'줄은'* element = C를 읽는 것이 이상적이다.CString (string (list [i]))' – jimt

+0

잠깐, C 구조체가 null로 끝나야 만하는 이유는 무엇입니까? 제가 문자열로 작업하고 있다고 가정하지 마십시오. 원시 데이터 버퍼로 작업하고 있습니다. 그렇다면 문자열 함수가 여전히 사용되어야합니까? –

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) [email protected]:~/src/tmp/SO/14833531$ go run main.go 
"Hello" 
"world" 
(15:25) [email protected]:~/src/tmp/SO/14833531$ 
+0

당신의 예는 무엇입니까 다음과 같이

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))) } 

출력은? 코드에 조금 더 자세히 설명해 주시겠습니까? – Kissaki

+0

이 예에서는 Go [] [] 바이트를 N 종료 C ** char로 변환 한 다음 C면에 출력합니다. 그게 네가 묻고있는거야? 그렇지 않다면 질문에 대해 자세히 설명해주십시오. – zzzz