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] }