在win7-64中调用dll时,golang syscall遇到一些问题

在win7-64中调用dll时,golang syscall遇到一些问题,go,system-calls,Go,System Calls,这是我的代码: package main import ( "fmt" "syscall" "unsafe" ) var ( WinSCard, _ = syscall.LoadLibrary("C:\\windows\\system32\\WinSCard.dll") procSCardListReaders, _ = syscall.GetProcAddress(WinSCard, "SCardListR

这是我的代码:

package main

import (
    "fmt"
    "syscall"
    "unsafe"
)

var (
    WinSCard, _                  = syscall.LoadLibrary("C:\\windows\\system32\\WinSCard.dll")
    procSCardListReaders, _      = syscall.GetProcAddress(WinSCard, "SCardListReaders")
    procSCardEstablishContext, _ = syscall.GetProcAddress(WinSCard, "SCardEstablishContext")
)

func abort(funcname string, err error) {
    panic(fmt.Sprintf("%s failed: %v", funcname, err))
}

func SCardEstablishContext(dwScope uint32, pvReserved1 *uint32, pvReserved2 *uint32, phContext uintptr) int32 {
    ret, _, callErr := syscall.Syscall6(uintptr(procSCardEstablishContext),
        4,
        uintptr(unsafe.Pointer(&dwScope)),
        uintptr(unsafe.Pointer(pvReserved1)),
        uintptr(unsafe.Pointer(pvReserved2)),
        phContext,
        0,
        0)
    if callErr != 0 {
        abort("Err:", callErr)
    }
    return int32(ret)
}

func main() {
    var Hwd uintptr
    defer syscall.FreeLibrary(WinSCard)
    rt := SCardEstablishContext(0, nil, nil, Hwd)
    fmt.Println(rt)
}
Return-2146435068表示0x8010004表示SCARD_E_无效参数。无法正确解释提供的一个或多个参数

func ScardesttablishContext:

LONG WINAPI SCardEstablishContext(
    _In_   DWORD dwScope,
    _In_   LPCVOID pvReserved1,
    _In_   LPCVOID pvReserved2,
    _Out_  LPSCARDCONTEXT phContext
)
我的参数有什么问题?太多了

怎么样

func SCardListReaders(hContext *syscall.Handle, mszGroups string, mszReaders *byte, pcchReaders *uint32) (err error) {
r1, _, e1 := syscall.Syscall6(
    uintptr(procSCardListReaders),
    4,
    uintptr(unsafe.Pointer(hContext)),
    uintptr(unsafe.Pointer(syscall.StringBytePtr(mszGroups))),
    uintptr(unsafe.Pointer(mszReaders)),
    uintptr(unsafe.Pointer(pcchReaders)),
    0,
    0,
)
if r1 != 0 {
    if e1 != 0 {
        err = error(e1)
    } else {
        err = syscall.EINVAL
    }
}
return
}

var Groups string
var Readers byte
var pcchReaders uint32
er1 := SCardListReaders(&context, Groups, &Readers, &pcchReaders)
if er1 != nil {
    fmt.Println("SCardListReaders:", er1)
    return
}
return:无效参数

例如

package main

import (
    "fmt"
    "syscall"
    "unicode/utf16"
    "unsafe"
)

var (
    WinSCard, _                  = syscall.LoadLibrary(`C:\windows\system32\WinSCard.dll`)
    procSCardEstablishContext, _ = syscall.GetProcAddress(WinSCard, "SCardEstablishContext")
    procSCardReleaseContext, _   = syscall.GetProcAddress(WinSCard, "SCardReleaseContext")
    procSCardListReaders, _      = syscall.GetProcAddress(WinSCard, "SCardListReadersW")
)

const (
    SCARD_SCOPE_USER   = 0
    SCARD_SCOPE_SYSTEM = 2

    SCARD_ALL_READERS     = "SCard$AllReaders"
    SCARD_DEFAULT_READERS = "SCard$DefaultReaders"
)

func SCardListReaders(hContext syscall.Handle, mszGroups *uint16, mszReaders *uint16, pcchReaders *uint32) (retval error) {
    r0, _, _ := syscall.Syscall6(
        uintptr(procSCardListReaders),
        4,
        uintptr(hContext),
        uintptr(unsafe.Pointer(mszGroups)),
        uintptr(unsafe.Pointer(mszReaders)),
        uintptr(unsafe.Pointer(pcchReaders)),
        0,
        0,
    )
    if r0 != 0 {
        retval = syscall.Errno(r0)
    }
    return
}

func SCardReleaseContext(hContext syscall.Handle) (retval error) {
    r0, _, _ := syscall.Syscall(
        uintptr(procSCardReleaseContext),
        1,
        uintptr(hContext),
        0,
        0,
    )
    if r0 != 0 {
        retval = syscall.Errno(r0)
    }
    return
}

func SCardEstablishContext(dwScope uint32, pvReserved1 uintptr, pvReserved2 uintptr, phContext *syscall.Handle) (retval error) {
    r0, _, _ := syscall.Syscall6(
        uintptr(procSCardEstablishContext),
        4,
        uintptr(dwScope),
        uintptr(pvReserved1),
        uintptr(pvReserved2),
        uintptr(unsafe.Pointer(phContext)),
        0,
        0,
    )
    if r0 != 0 {
        retval = syscall.Errno(r0)
    }
    return
}

func ReturnValue(err error) uint32 {
    rv, ok := err.(syscall.Errno)
    if !ok {
        rv = 0
    }
    return uint32(rv)
}

func UTF16ToStrings(ls []uint16) []string {
    var ss []string
    if len(ls) == 0 {
        return ss
    }
    if ls[len(ls)-1] != 0 {
        ls = append(ls, 0)
    }
    i := 0
    for j, cu := range ls {
        if cu == 0 {
            if j >= 1 && ls[j-1] == 0 {
                break
            }
            if j-i > 0 {
                ss = append(ss, string(utf16.Decode(ls[i:j])))
            }
            i = j + 1
            continue
        }
    }
    return ss
}

func main() {
    var (
        context  syscall.Handle
        scope    uint32
        groups   *uint16
        cReaders uint32
    )

    context = 0
    groups, err := syscall.UTF16PtrFromString(SCARD_ALL_READERS)
    if err != nil {
        fmt.Println("Reader Group: ", err)
        return
    }
    err = SCardListReaders(context, groups, nil, &cReaders)
    if err != nil {
        fmt.Printf("SCardListReaders: 0x%X %s\n", ReturnValue(err), err)
        return
    }
    r := make([]uint16, cReaders)
    err = SCardListReaders(context, groups, &r[0], &cReaders)
    if err != nil {
        fmt.Printf("SCardListReaders: 0x%X %s\n", ReturnValue(err), err)
        return
    }
    readers := UTF16ToStrings(r[:cReaders])
    fmt.Println("Readers:", len(readers), readers)

    scope = SCARD_SCOPE_SYSTEM
    err = SCardEstablishContext(scope, 0, 0, &context)
    if err != nil {
        fmt.Printf("SCardEstablishContext: 0x%X %s\n", ReturnValue(err), err)
        return
    }
    defer SCardReleaseContext(context)
    fmt.Printf("Context: %X\n", context)
}
输出:

计算机1:

Readers: 1 [O2 O2Micro CCID SC Reader 0]
Context: CD00000100000000
计算机2:

Readers: 0 []
SCardEstablishContext: 0x8010001D The Smart card resource manager is not running.
另外,请注意
procSCardListReaders
ProcName
的修复程序:

procSCardListReaders, _ = syscall.GetProcAddress(WinSCard, "SCardListReadersW")
比如说,

package main

import (
    "fmt"
    "syscall"
    "unicode/utf16"
    "unsafe"
)

var (
    WinSCard, _                  = syscall.LoadLibrary(`C:\windows\system32\WinSCard.dll`)
    procSCardEstablishContext, _ = syscall.GetProcAddress(WinSCard, "SCardEstablishContext")
    procSCardReleaseContext, _   = syscall.GetProcAddress(WinSCard, "SCardReleaseContext")
    procSCardListReaders, _      = syscall.GetProcAddress(WinSCard, "SCardListReadersW")
)

const (
    SCARD_SCOPE_USER   = 0
    SCARD_SCOPE_SYSTEM = 2

    SCARD_ALL_READERS     = "SCard$AllReaders"
    SCARD_DEFAULT_READERS = "SCard$DefaultReaders"
)

func SCardListReaders(hContext syscall.Handle, mszGroups *uint16, mszReaders *uint16, pcchReaders *uint32) (retval error) {
    r0, _, _ := syscall.Syscall6(
        uintptr(procSCardListReaders),
        4,
        uintptr(hContext),
        uintptr(unsafe.Pointer(mszGroups)),
        uintptr(unsafe.Pointer(mszReaders)),
        uintptr(unsafe.Pointer(pcchReaders)),
        0,
        0,
    )
    if r0 != 0 {
        retval = syscall.Errno(r0)
    }
    return
}

func SCardReleaseContext(hContext syscall.Handle) (retval error) {
    r0, _, _ := syscall.Syscall(
        uintptr(procSCardReleaseContext),
        1,
        uintptr(hContext),
        0,
        0,
    )
    if r0 != 0 {
        retval = syscall.Errno(r0)
    }
    return
}

func SCardEstablishContext(dwScope uint32, pvReserved1 uintptr, pvReserved2 uintptr, phContext *syscall.Handle) (retval error) {
    r0, _, _ := syscall.Syscall6(
        uintptr(procSCardEstablishContext),
        4,
        uintptr(dwScope),
        uintptr(pvReserved1),
        uintptr(pvReserved2),
        uintptr(unsafe.Pointer(phContext)),
        0,
        0,
    )
    if r0 != 0 {
        retval = syscall.Errno(r0)
    }
    return
}

func ReturnValue(err error) uint32 {
    rv, ok := err.(syscall.Errno)
    if !ok {
        rv = 0
    }
    return uint32(rv)
}

func UTF16ToStrings(ls []uint16) []string {
    var ss []string
    if len(ls) == 0 {
        return ss
    }
    if ls[len(ls)-1] != 0 {
        ls = append(ls, 0)
    }
    i := 0
    for j, cu := range ls {
        if cu == 0 {
            if j >= 1 && ls[j-1] == 0 {
                break
            }
            if j-i > 0 {
                ss = append(ss, string(utf16.Decode(ls[i:j])))
            }
            i = j + 1
            continue
        }
    }
    return ss
}

func main() {
    var (
        context  syscall.Handle
        scope    uint32
        groups   *uint16
        cReaders uint32
    )

    context = 0
    groups, err := syscall.UTF16PtrFromString(SCARD_ALL_READERS)
    if err != nil {
        fmt.Println("Reader Group: ", err)
        return
    }
    err = SCardListReaders(context, groups, nil, &cReaders)
    if err != nil {
        fmt.Printf("SCardListReaders: 0x%X %s\n", ReturnValue(err), err)
        return
    }
    r := make([]uint16, cReaders)
    err = SCardListReaders(context, groups, &r[0], &cReaders)
    if err != nil {
        fmt.Printf("SCardListReaders: 0x%X %s\n", ReturnValue(err), err)
        return
    }
    readers := UTF16ToStrings(r[:cReaders])
    fmt.Println("Readers:", len(readers), readers)

    scope = SCARD_SCOPE_SYSTEM
    err = SCardEstablishContext(scope, 0, 0, &context)
    if err != nil {
        fmt.Printf("SCardEstablishContext: 0x%X %s\n", ReturnValue(err), err)
        return
    }
    defer SCardReleaseContext(context)
    fmt.Printf("Context: %X\n", context)
}
输出:

计算机1:

Readers: 1 [O2 O2Micro CCID SC Reader 0]
Context: CD00000100000000
计算机2:

Readers: 0 []
SCardEstablishContext: 0x8010001D The Smart card resource manager is not running.
另外,请注意
procSCardListReaders
ProcName
的修复程序:

procSCardListReaders, _ = syscall.GetProcAddress(WinSCard, "SCardListReadersW")

我已经修改了我的答案来回答第二个问题,我也对第一个问题的答案进行了改进。错误处理得到了很大的改进。您现在可以获得返回值以及格式化的消息文本。我差点错过了你修改过的问题,因为这个问题已经被回答和接受了。下一次,发布一个新的问题,以便于查看。我已经修改了我的答案,以进一步简化
syscall
返回值的代码。这有助于我在Windows的机器上获得openCL的syscall。我之所以这么做是因为CUDA TOOLKIT for windows没有提供可链接的.a文件。CGO使用mingw。但我不明白为什么忽略syscall9的第三个输出会起作用。为什么它会包含错误代码#203,但仍然有效?我已经修改了回答第二个问题的答案,并且对第一个问题的答案进行了改进。错误处理得到了很大的改进。您现在可以获得返回值以及格式化的消息文本。我差点错过了你修改过的问题,因为这个问题已经被回答和接受了。下一次,发布一个新的问题,以便于查看。我已经修改了我的答案,以进一步简化
syscall
返回值的代码。这有助于我在Windows的机器上获得openCL的syscall。我之所以这么做是因为CUDA TOOLKIT for windows没有提供可链接的.a文件。CGO使用mingw。但我不明白为什么忽略syscall9的第三个输出会起作用。为什么它会包含错误代码#203,但仍然有效?