2017-04-08 8 views
1

Go에서 EDSDK DLL을 사용하여 Canon DSLR을 제어하는 ​​패키지를 작성하고 있습니다."LockOSThread"GoRoutine 내부 함수 호출

이것은 내 파트너 요청시 사진 부스에서 사용할 수있는 개인 프로젝트입니다. 완료되면 GitHub에 게시 해 드리겠습니다 :).

다른 곳에서 SDK를 사용하는 예제를 보면 스레드 안전하지 않으며 스레드 로컬 리소스를 사용하기 때문에 사용하는 동안 단일 스레드에서 호출해야합니다. 이상적인 것은 아니지만, Go가 "runtime.LockOSThread"함수를 제공하는 것처럼 보입니다. 핵심 DLL interop 코드 자체에서 호출 되기는하지만 그렇게 할 수는 없으므로 기다려야합니다.

스레드의 걱정없이 상위 수준 인터페이스를 사용하여 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

귀하의 질문은 너무 복잡 할 수 있습니다. 코드에서 하나의 관심사로 끓여보십시오. – eduncan911

답변

0

, 나는 그 USB 장치를 통해 모든 작업을 수행하는 채널에서 수신 대기 단일 goroutine 노동자를 생성하는 경향이있다. 결과가 다른 채널에서 다시 전송됩니다.

단방향 교환으로 이동중인 채널 만 사용하여 대화를 나눕니다. 다른 채널의 응답을 기다립니다.

USB는 직렬 및 폴링이므로 다른 goroutine을 사용하여 전용 채널을 설정해야했습니다. 그냥 루핑 된 직원 goroutine에서 채널로 항목을 밀어 넣을 때 채널에서 항목을 선택합니다.