Heim > Backend-Entwicklung > Golang > Übergeben Sie das 2D-Array von Go an C mit runtime.Pinner

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

PHPz
Freigeben: 2024-02-12 17:51:05
nach vorne
660 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 ü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>
Nach dem Login kopieren

Ist diese Implementierung sicher? Kann ich einen Zeiger auf die resultDaten ü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>
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 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!

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
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage