diff --git a/11.C_ByteSliceToCharPtr/README.md b/11.C_ByteSliceToCharPtr/README.md new file mode 100644 index 0000000..07a78e1 --- /dev/null +++ b/11.C_ByteSliceToCharPtr/README.md @@ -0,0 +1,15 @@ +# C.ByteSliceToCharPtr + +```C.CBytes()```を用いずに、```[]byte```を```(char *)```に変換するには以下の手順を踏む。 + +1. スライスの先頭要素のポインタを取得 +1. ```unsafe.Pointer```を取得 +1. (*C.char)にキャスト + +cgoでは、```unsafe.Pointer``` がCの ```(void *)``` に当たる。 + +Cの ```(void *)``` と同様に、```unsafe.Pointer``` も任意のポインタ型にキャストできる。 + +Cでは配列は「先頭要素のポインタ」を表しているが、Goではそれが出来ない。 + +なので、明示的に先頭要素のポインタを指定する必要がある。 diff --git a/11.C_ByteSliceToCharPtr/Taskfile.yml b/11.C_ByteSliceToCharPtr/Taskfile.yml new file mode 100644 index 0000000..a29c8f5 --- /dev/null +++ b/11.C_ByteSliceToCharPtr/Taskfile.yml @@ -0,0 +1,8 @@ +# https://taskfile.dev + +version: '3' + +tasks: + default: + cmds: + - go run main.go diff --git a/11.C_ByteSliceToCharPtr/main.go b/11.C_ByteSliceToCharPtr/main.go new file mode 100644 index 0000000..01167dd --- /dev/null +++ b/11.C_ByteSliceToCharPtr/main.go @@ -0,0 +1,39 @@ +package main + +/* +#include +#include +#include + +const int BUF_SIZE = 11; + +void setBuf(char *buf) { + strncpy(buf, "helloworld", BUF_SIZE); +} +*/ +import "C" +import ( + "encoding/hex" + "fmt" + "unsafe" +) + +func main() { + var ( + buf = make([]byte, int(C.BUF_SIZE)) + bufPtr = unsafe.Pointer(&buf[0]) //明示的に先頭要素のポインタを渡す + charPtr = (*C.char)(bufPtr) // (void *) --> (char *) + printBuf = func() { + fmt.Println(string(buf)) + fmt.Println(hex.Dump(buf)) + } + ) + + printBuf() + + // C側の宣言では (char *) を引数に要求しているため、unsafe.Pointer を *C.char にキャストして渡す. + // unsafe.Pointer は、 (void *) を表すので、任意のポインタ型にキャスト可能. + C.setBuf(charPtr) + + printBuf() +}