Übergeben Sie das 2D-Array von Go an C mit runtime.Pinner

PHPz
Freigeben: 2024-02-12 17:51:05
nach vorne
436 Leute haben es durchsucht

Übergeben Sie das 2D-Array von Go an C mit runtime.Pinner

Frageninhalt

Ich versuche, ein 2D-Array von Go an eine C-Funktion zu übergebenvoid 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:

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 } 
Nach dem Login kopieren

Ist diese Implementierung sicher? Kann ich einen Zeiger auf dieresultDaten ü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 demruntime.Pinner,它使指针固定直到runtime.Pinner.Unpin()-Aufruf. Ich habe versucht, eine andere Implementierung mit Pinner zu schreiben:

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 } 
Nach dem Login kopieren

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?)
Nach dem Login kopieren

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?

Lösung

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 Diskussionenhier一个>.

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!

Quelle:stackoverflow.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!