我正在编写一个程序包来控制使用Go的EDSDK DLL的佳能DSLR。
这是一个照相亭的个人项目,可以在我的合作伙伴要求下在我们的婚礼上使用,我很乐意在完成时在GitHub上发布:)。
查看在其他地方使用SDK的示例,它不是线程安全的并且使用线程本地资源,因此我需要确保在使用期间从单个线程调用它。虽然不理想,看起来Go提供了一个“runtime.LockOSThread”函数来做到这一点,虽然这确实被核心DLL互操作代码本身调用,所以我将不得不等待并找出是否干扰。
我希望应用程序的其余部分能够使用更高级别的接口调用SDK而不必担心线程,所以我需要一种方法将函数调用请求传递给锁定的线程/ Goroutine来执行,然后传递结果回到了Goroutine之外的调用函数。
到目前为止,我已经提出了这个使用[] interface {}数组并通过通道前后传递的非常广泛的函数定义的工作示例。这会在每次调用时对接口{}数组中的类型断言进行大量的输入/输出数据修改,即使我们知道我们应该提前对每个函数做什么,但它看起来像是工作
在我投入大量时间之前,这可能是最糟糕的做法 - 有没有人有更好的选择?
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 }
}
答案 0 :(得分:0)
对于我曾经玩过的类似的嵌入式项目,我倾向于创建一个单独的goroutine工作者,该工作人员通过通道监听该USB设备上的所有工作。任何结果都会在另一个频道上发回。
仅在Go进行单向交换时与设备通信。 LIsten来自其他频道的回复。
由于USB是串行和轮询,我不得不设置一个专用通道与另一个goroutine,当它们从刚刚循环的工作器goroutine推入它时,只需从通道中选择项目。