I am learning go and cgo and ffi, I have the header file below:
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
typedef struct MyStruct3 {
const char *const *data;
int length;
} MyStruct3;
void my_struct_3(const struct MyStruct3 *c_data);
And this go file
package main
/*
#cgo LDFLAGS: -L./release -lrust_ffi
#cgo CFLAGS: -I./target
#include <rust-ffi.h>
*/
import "C"
import (
"fmt"
"unsafe"
)
func main() {
type MyStruct3 struct {
data **C.char
length C.int
}
goStrings2 := []string{"Hello", "World", "from", "Go", "again"}
pnr := new(runtime.Pinner)
cStrings2 := make([]*C.char, len(goStrings2))
for i, s := range goStrings2 {
cString := C.CString(s)
cStrings2[i] = cString
// pnr.Pin(cString)
defer C.free(unsafe.Pointer(cStrings2[i]))
}
cDataPtr := (**C.char)(unsafe.Pointer(&cStrings2[0]))
// pnr.Pin(&goStrings2)
pnr.Pin(&cDataPtr)
// cLength := C.int(len(goStrings2))
// pnr.Pin(&cLength)
cStruct3 := MyStruct3{
data: cDataPtr,
length: C.int(len(goStrings2)),
}
cStruct3prt := (*C.struct_MyStruct3)(unsafe.Pointer(&cStruct3))
pnr.Pin(&cStruct3)
C.my_struct_3(cStruct3prt)
pnr.Unpin()
I am getting the following error
panic: runtime error: cgo argument has Go pointer to unpinned Go pointer
Go version
$ go version
go version go1.21.5 linux/amd64
Any idea on how to solve this issue?
thank you very much
Since the slice is allocated by the Go runtime, you have to pin it:
func main() {
goStrings2 := []string{"Hello", "World", "from", "Go", "again"}
// Convert Go slice to a C array of C strings
cStrings2 := make([]*C.char, len(goStrings2))
for i, s := range goStrings2 {
cStrings2[i] = C.CString(s)
defer C.free(unsafe.Pointer(cStrings2[i]))
}
var pin runtime.Pinner
defer pin.Unpin()
cData := &cStrings2[0]
pin.Pin(cData)
C.my_struct_3(&C.MyStruct3{
data: cData,
length: C.int(len(goStrings2)),
})
}