42 lines
790 B
Go
42 lines
790 B
Go
|
|
package win32api
|
||
|
|
|
||
|
|
import (
|
||
|
|
"fmt"
|
||
|
|
"sync"
|
||
|
|
"syscall"
|
||
|
|
)
|
||
|
|
|
||
|
|
var (
|
||
|
|
procCacheMu sync.Mutex
|
||
|
|
dllCache = map[string]syscall.Handle{}
|
||
|
|
procCache = map[string]uintptr{}
|
||
|
|
)
|
||
|
|
|
||
|
|
func getProcAddr(dllName, procName string) (uintptr, error) {
|
||
|
|
cacheKey := dllName + "!" + procName
|
||
|
|
|
||
|
|
procCacheMu.Lock()
|
||
|
|
defer procCacheMu.Unlock()
|
||
|
|
|
||
|
|
if proc, ok := procCache[cacheKey]; ok {
|
||
|
|
return proc, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
dll, ok := dllCache[dllName]
|
||
|
|
if !ok {
|
||
|
|
var err error
|
||
|
|
dll, err = syscall.LoadLibrary(dllName)
|
||
|
|
if err != nil {
|
||
|
|
return 0, fmt.Errorf("load %s: %w", dllName, err)
|
||
|
|
}
|
||
|
|
dllCache[dllName] = dll
|
||
|
|
}
|
||
|
|
|
||
|
|
proc, err := syscall.GetProcAddress(syscall.Handle(dll), procName)
|
||
|
|
if err != nil {
|
||
|
|
return 0, fmt.Errorf("resolve %s!%s: %w", dllName, procName, err)
|
||
|
|
}
|
||
|
|
procCache[cacheKey] = proc
|
||
|
|
return proc, nil
|
||
|
|
}
|