Heim >Backend-Entwicklung >Golang >Übergeben Sie das 2D-Array von Go an C mit runtime.Pinner
Ich versuche, ein 2D-Array von Go an eine C-Funktion zu übergeben void foo(in **float, out *double)
。因为我想要这个 C 函数的包装器,所以我希望 Go 函数具有像 func FooWrapper([][]float32) []float64
, die so definiert ist. Die einfachste, aber nicht sehr effiziente Implementierung besteht darin, den gesamten Speicher über das unten aufgeführte C zuzuweisen:
<code>func FooWrapper(values [][]float32) []float64 { totalObj := len(values) totalParams := len(values[0]) results := make([]float64, totalObj) ptrArrLength := uintptr(totalObj) * cPointerSize paramArrLength := uintptr(totalParams) * cFloatSize ptr := C.malloc(C.size_t(ptrArrLength + paramArrLength*uintptr(totalObj))) defer C.free(ptr) ptrSlice := unsafe.Slice((**C.float)(ptr), totalObj) for i, obj := range values { paramArrPtr := (*C.float)(unsafe.Add(ptr, ptrArrLength+uintptr(i)*paramArrLength)) ptrSlice[i] = paramArrPtr paramSlice := unsafe.Slice(paramArrPtr, totalParams) for j, param := range obj { paramSlice[j] = (C.float)(param) } } C.foo((**C.float)(ptr), (*C.double)(&results[0])) return results } </code>
Ist diese Implementierung sicher? Kann ich einen Zeiger auf die result
Daten übergeben? Soweit ich weiß, wird dieser Zeiger behoben, da er an die C-Funktion übergeben wird.
Aber ich möchte weniger Speicher zuweisen und einfach Go-Speicher wiederverwenden, ich weiß bereits von dem runtime.Pinner
,它使指针固定直到 runtime.Pinner.Unpin()
-Aufruf. Ich habe versucht, eine andere Implementierung mit Pinner zu schreiben:
<code>func FooWrapper(values [][]float32) []float64 { length := len(values) results := make([]float64, length) pinner := runtime.Pinner{} defer pinner.Unpin() arr := (**C.float)(C.malloc(C.size_t(uintptr(length) * cPointerSize))) defer C.free(unsafe.Pointer(arr)) slice := unsafe.Slice(arr, length) for i, v := range values { pinner.Pin(&v[0]) slice[i] = (*C.float)(&v[0]) } C.foo(arr, (*C.double)(&results[0])) return results } </code>
Aber leider funktioniert dieser Code nicht
runtime: pointer 0xc016ecbfc0 to unused region of span span.base()=0xc016eca000 span.limit=0xc016ecbfa0 span.state=1 fatal error: found bad pointer in Go heap (incorrect use of unsafe or cgo?)
Verwende ich runtime.Pinner falsch (soweit ich weiß, kann ich Slice-Daten anpinnen)? Oder es gibt einen anderen Fehler in diesem Code. Gibt es eine Implementierung zur Übergabe eines 3D-Arrays (4D usw.) an eine C-Funktion neben der Zuweisung und dem Kopieren aller Daten in den C-Speicher?
Ich habe die Antwort auf mein Problem gefunden. Die Verwendung von malloc ist gefährlich, denn wenn ich versuche, einen Go-Zeiger in den C-Speicher zu schreiben, kann der GC nicht initialisierten Speicher als „schlechten“ Speicher erkennen. Wenn ich also malloc in calloc ändere, gibt es kein Problem. Natürlich ist dies nicht die beste Lösung. Es ist besser, Speicher in Go zuzuweisen, da dies schneller und sicherer ist.
Alle Diskussionen hier一个>.
Das obige ist der detaillierte Inhalt vonÜbergeben Sie das 2D-Array von Go an C mit runtime.Pinner. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!