Ich schreibe ein Paket zur Steuerung einer Canon DSLR mit ihrer EDSDK DLL von Go.Aufruf von Funktionen in einer "LockOSThread" GoRoutine
Dies ist ein persönliches Projekt für eine Fotokabine zu unserer Hochzeit bei meiner Partner Anfrage, die ich gerne auf GitHub veröffentlichen werde, wenn abgeschlossen :).
Wenn Sie sich die Beispiele für die Verwendung des SDK an anderer Stelle ansehen, ist es kein threadsicheres Werkzeug und verwendet thread-lokale Ressourcen. Daher muss ich sicherstellen, dass ich es während der Verwendung aus einem einzigen Thread heraus aufruft. Obwohl es nicht ideal ist, sieht es so aus, als ob Go eine "runtime.LockOSThread" -Funktion bereitstellt, obwohl das vom internen DLL-Interop-Code selbst aufgerufen wird, also muss ich warten und herausfinden, ob das stört oder nicht.
Ich möchte den Rest der Anwendung in der Lage sein, das SDK über eine höhere Ebene Schnittstelle ohne sich über die Threading zu kümmern, so brauche ich eine Möglichkeit, Funktionsaufruf an den gesperrten Thread/Goroutine übergeben, um dort auszuführen Übergeben Sie die Ergebnisse an die aufrufende Funktion außerhalb dieser Goroutine zurück.
Bisher habe ich dieses Arbeitsbeispiel für die Verwendung sehr breiter Funktionsdefinitionen unter Verwendung von [] Interface {} - Arrays und für die Vor- und Zurückübertragung über Kanäle entwickelt. Dies würde bei jedem Aufruf eine Menge an Eingabe-/Ausgabedaten erfordern, um Assertions wieder aus dem Array der Schnittstelle {} herauszulösen, selbst wenn wir wissen, was wir für jede Funktion im voraus erwarten sollten, aber es sieht so aus Arbeit.
Bevor ich viel Zeit auf diese Weise für möglicherweise den schlechtesten Weg zu tun investieren - hat jemand bessere Möglichkeiten?
package edsdk
import (
"fmt"
"runtime"
)
type CanonSDK struct {
FChan chan functionCall
}
type functionCall struct {
Function func([]interface{}) []interface{}
Arguments []interface{}
Return chan []interface{}
}
func NewCanonSDK() (*CanonSDK, error) {
c := &CanonSDK {
FChan: make(chan functionCall),
}
go c.BackgroundThread(c.FChan)
return c, nil
}
func (c *CanonSDK) BackgroundThread(fcalls <-chan functionCall) {
runtime.LockOSThread()
for f := range fcalls {
f.Return <- f.Function(f.Arguments)
}
runtime.UnlockOSThread()
}
func (c *CanonSDK) TestCall() {
ret := make(chan []interface{})
f := functionCall {
Function: c.DoTestCall,
Arguments: []interface{}{},
Return: ret,
}
c.FChan <- f
results := <- ret
close(ret)
fmt.Printf("%#v", results)
}
func (c *CanonSDK) DoTestCall([]interface{}) []interface{} {
return []interface{}{ "Test", nil }
}
Ihre Frage könnte für SO zu komplex sein. Versuchen Sie, es auf eine einzige Sorge in Code herunterzukochen. – eduncan911