112 lines
2.8 KiB
Go
112 lines
2.8 KiB
Go
package interceptor
|
||
|
||
import (
|
||
"fmt"
|
||
"path/filepath"
|
||
"reflect"
|
||
"strings"
|
||
|
||
"github.com/ebitengine/purego"
|
||
)
|
||
|
||
type funcType struct {
|
||
ParamTypes []string
|
||
ReturnTypes []string
|
||
}
|
||
|
||
var typeMap = map[string]reflect.Type{
|
||
"int": reflect.TypeOf(int(0)),
|
||
"int32": reflect.TypeOf(int32(0)),
|
||
"int64": reflect.TypeOf(int64(0)),
|
||
"uint": reflect.TypeOf(uint(0)),
|
||
"float32": reflect.TypeOf(float32(0)),
|
||
"float64": reflect.TypeOf(float64(0)),
|
||
"string": reflect.TypeOf(""),
|
||
"bool": reflect.TypeOf(false),
|
||
"void": nil, // 用于表示无返回值
|
||
}
|
||
|
||
func makeFuncType(paramTypes, returnTypes []string) (reflect.Type, error) {
|
||
var in, out []reflect.Type
|
||
|
||
// 参数类型
|
||
for _, t := range paramTypes {
|
||
rt, ok := typeMap[t]
|
||
if !ok {
|
||
return nil, fmt.Errorf("unknown parameter type: %s", t)
|
||
}
|
||
in = append(in, rt)
|
||
}
|
||
|
||
// 返回值类型
|
||
for _, t := range returnTypes {
|
||
if t == "void" {
|
||
continue // 无返回值
|
||
}
|
||
rt, ok := typeMap[t]
|
||
if !ok {
|
||
return nil, fmt.Errorf("unknown return type: %s", t)
|
||
}
|
||
out = append(out, rt)
|
||
}
|
||
|
||
return reflect.FuncOf(in, out, false), nil
|
||
}
|
||
|
||
func (a *Ankointerceptor) loadLibrary(libPath string, libFuncMap map[string]funcType) interface{} {
|
||
libName := filepath.Base(libPath)
|
||
libName = strings.TrimSuffix(libName, filepath.Ext(".dll"))
|
||
// 是不是so文件?libName里边是否包含.so
|
||
if strings.Contains(libName, ".so") {
|
||
soIndex := strings.Index(libName, ".so")
|
||
libName = libName[0:soIndex]
|
||
|
||
}
|
||
libName = strings.TrimPrefix(libName, "lib")
|
||
if _, ok := a.libMap[libName]; ok {
|
||
return a.libMap[libName] // 如果已经加载过,直接返回
|
||
}
|
||
lib, err := purego.Dlopen(libPath, purego.RTLD_LAZY)
|
||
if err != nil {
|
||
panic("Load library error")
|
||
}
|
||
a.libhabdles = append(a.libhabdles, lib)
|
||
fnmap := make(map[string]interface{})
|
||
fileds := make([]reflect.StructField, 0, len(fnmap))
|
||
for name, types := range libFuncMap {
|
||
ft, err := makeFuncType(types.ParamTypes, types.ReturnTypes)
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
fn := reflect.New(ft).Elem().Addr().Interface()
|
||
purego.RegisterLibFunc(fn, lib, name)
|
||
|
||
//Get ft 指针类型
|
||
// ftp := reflect.PtrTo(ft)
|
||
fileds = append(fileds, reflect.StructField{
|
||
Name: name,
|
||
Type: ft,
|
||
})
|
||
fnmap[name] = fn
|
||
}
|
||
|
||
// 根据fnmap构建一个匿名结构体,结构体的字段名为函数名,字段值为函数指针
|
||
libstruct := reflect.StructOf(fileds)
|
||
// 创建一个匿名结构体的实例
|
||
libinstance := reflect.New(libstruct).Elem()
|
||
for name, fn := range fnmap {
|
||
// 将函数指针指向的函数设置到结构体实例的对应字段中
|
||
libinstance.FieldByName(name).Set(reflect.ValueOf(fn).Elem())
|
||
// libinstance.FieldByName(name).Set()
|
||
}
|
||
a.libMap[libName] = libinstance.Interface()
|
||
|
||
return a.libMap[libName]
|
||
}
|
||
|
||
func (a *Ankointerceptor) Close() {
|
||
for _, lib := range a.libhabdles {
|
||
purego.Dlclose(lib)
|
||
}
|
||
}
|