├── Demo └── NewDLL │ ├── Func.go │ ├── LoadCore.go │ ├── config.go │ └── test.dll ├── LICENSE ├── LoadC.c ├── LoadC.dll ├── LoadDll ├── Load.go └── Type.go ├── Public └── public.go ├── README.md ├── go.mod ├── test.dll └── test.go /Demo/NewDLL/Func.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | public "TestDLL/Public" 5 | "fmt" 6 | ) 7 | 8 | func Demo(Value map[int]string) public.TypeDLL { 9 | fmt.Println(Value, "") 10 | for _, v := range Value { 11 | fmt.Println(v) 12 | } 13 | public.Tmp = 2 14 | return public.TypeDLL{ 15 | Is_Array: false, 16 | Text: "你好", 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Demo/NewDLL/LoadCore.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "C" 4 | import ( 5 | public "TestDLL/Public" 6 | "fmt" 7 | "unsafe" 8 | ) 9 | 10 | //export INITGODLL 11 | func INITGODLL(Map uintptr, LoadFuncName uintptr) uintptr { 12 | INITS() 13 | TmpMap := PtrMap(Map) 14 | FuncName := uintptrToString(LoadFuncName) 15 | if _, ok := ConfigMap[FuncName]; ok { 16 | TmpRes := ConfigMap[FuncName](TmpMap) 17 | fmt.Scanln(TmpRes) 18 | return NewRes(&TmpRes) 19 | } 20 | 21 | NewResT := public.TypeDLL{ 22 | Is_Array: false, 23 | Text: "", 24 | } 25 | fmt.Scanln(NewRes(&NewResT)) //进入GC不让其消失 26 | panic("ERROR NOT FUNC") 27 | return NewRes(&NewResT) 28 | } 29 | 30 | //export INITREADALL 31 | func INITREADALL() uintptr { 32 | INITS() 33 | TmpMap := make(map[int][]byte) 34 | for k, _ := range ConfigMap { 35 | TmpMap[len(TmpMap)] = []byte(k) 36 | } 37 | fmt.Scanln(MapPtr(&TmpMap)) 38 | return MapPtr(&TmpMap) 39 | } 40 | 41 | func NewRes(Structs *public.TypeDLL) uintptr { 42 | 43 | Structss := public.Type{ 44 | Is_Array: Structs.Is_Array, 45 | Text: []byte(Structs.Text), 46 | } 47 | 48 | return uintptr(unsafe.Pointer(&Structss)) 49 | } 50 | 51 | func uintptrToString(ptr uintptr) string { 52 | return *(*string)(unsafe.Pointer(ptr)) 53 | } 54 | 55 | func StrPtr(s *string) uintptr { 56 | return uintptr(unsafe.Pointer(s)) 57 | } 58 | 59 | func PtrMap(ptr uintptr) map[int]string { 60 | res := make(map[int]string) 61 | tmp := *(*map[int][]byte)(unsafe.Pointer(ptr)) 62 | for k, v := range tmp { 63 | res[k] = string(v) 64 | } 65 | return res 66 | } 67 | 68 | func MapPtr(m *map[int][]byte) uintptr { 69 | return uintptr(unsafe.Pointer(m)) 70 | } 71 | 72 | func main() { 73 | 74 | } 75 | -------------------------------------------------------------------------------- /Demo/NewDLL/config.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | public "TestDLL/Public" 5 | ) 6 | 7 | var ConfigMap = make(map[string]func(map[int]string) public.TypeDLL) 8 | 9 | func INITS() { 10 | /* v 请在这里配置函数*/ 11 | ConfigMap["Demo"] = Demo 12 | /* ^ 请在这里配置函数*/ 13 | } 14 | -------------------------------------------------------------------------------- /Demo/NewDLL/test.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Linkangyis/GoLangLinkDLL/818a5b2268a7639cf93018fe8ebc69dbea3841e3/Demo/NewDLL/test.dll -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Linkin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LoadC.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | typedef void (*MyMessageBox)(void*,char*); 5 | typedef void (*MyMessageBoxConfig)(); 6 | 7 | void INITCDLL(char* file,char* INITNAME,void* FuncName,void* MapList){ 8 | HMODULE hModule=LoadLibrary(file); 9 | MyMessageBox NewMessageBox=(MyMessageBox)GetProcAddress(hModule,INITNAME); 10 | return NewMessageBox(MapList,FuncName); 11 | } 12 | 13 | void READCONFIG(char* file,char* INITNAME){ 14 | HMODULE hModule=LoadLibrary(file); 15 | MyMessageBoxConfig NewMessageBox=(MyMessageBox)GetProcAddress(hModule,INITNAME); 16 | return NewMessageBox(); 17 | } 18 | 19 | /* 20 | typedef void (*MyMessageBox)(void*); 21 | 22 | void Test(char file[],char FuncName[],void *MapList){ 23 | HMODULE hModule=LoadLibrary(file); 24 | MyMessageBox NewMessageBox=(MyMessageBox)GetProcAddress(hModule,FuncName); 25 | return NewMessageBox(MapList); 26 | } 27 | */ -------------------------------------------------------------------------------- /LoadC.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Linkangyis/GoLangLinkDLL/818a5b2268a7639cf93018fe8ebc69dbea3841e3/LoadC.dll -------------------------------------------------------------------------------- /LoadDll/Load.go: -------------------------------------------------------------------------------- 1 | package load 2 | 3 | import ( 4 | "TestDLL/Public" 5 | "syscall" 6 | ) 7 | 8 | const CDLLFILE = "./LoadC.dll" 9 | 10 | var MessageBoxW *syscall.LazyProc 11 | var MessageBoxConfig *syscall.LazyProc 12 | 13 | type DLLFILE string 14 | 15 | func init() { 16 | var TmpMap = make(map[int][]byte) 17 | TmpMap[0] = []byte("Test") 18 | read := syscall.NewLazyDLL(CDLLFILE) 19 | MessageBoxW = read.NewProc("INITCDLL") 20 | MessageBoxConfig = read.NewProc("READCONFIG") 21 | } 22 | 23 | func OpenDLL(File string) DLLFILE { 24 | return DLLFILE(File) 25 | } 26 | 27 | func (GoDLLfile DLLFILE) LoadFunc(funcName string) func(map[int]string) public.TypeDLL { 28 | return func(Value map[int]string) public.TypeDLL { 29 | ValueByte := make(map[int][]byte) 30 | for k, v := range Value { 31 | ValueByte[k] = []byte(v) 32 | } 33 | TmpfuncName := &funcName 34 | Res, _, _ := MessageBoxW.Call(CtsrPtr(string(GoDLLfile)), CtsrPtr("INITGODLL"), StrPtr(TmpfuncName), uintptrToMapS_I(&ValueByte)) 35 | return FuncRes(Res) 36 | } 37 | } 38 | 39 | func (GoDLLfile DLLFILE) ReadConfig() map[int]string { 40 | Res, _, _ := MessageBoxConfig.Call(CtsrPtr(string(GoDLLfile)), CtsrPtr("INITREADALL")) 41 | TmpMap := uintptrToMapI_S(Res) 42 | ResMap := make(map[int]string) 43 | for k, v := range TmpMap { 44 | ResMap[k] = string(v) 45 | } 46 | return ResMap 47 | } 48 | -------------------------------------------------------------------------------- /LoadDll/Type.go: -------------------------------------------------------------------------------- 1 | package load 2 | 3 | import "C" 4 | import ( 5 | "TestDLL/Public" 6 | "unsafe" 7 | ) 8 | 9 | func CtsrPtr(s string) uintptr { 10 | return uintptr(unsafe.Pointer(C.CString(s))) 11 | } 12 | func FuncRes(ptr uintptr) public.TypeDLL { 13 | Tmp := *(*public.Type)(unsafe.Pointer(ptr)) 14 | return public.TypeDLL{ 15 | Is_Array: Tmp.Is_Array, 16 | Text: string(Tmp.Text), 17 | } 18 | } 19 | func uintptrToString(ptr uintptr) string { 20 | return *(*string)(unsafe.Pointer(ptr)) 21 | } 22 | func uintptrToMapI_S(ptr uintptr) map[int][]byte { 23 | return *(*map[int][]byte)(unsafe.Pointer(ptr)) 24 | } 25 | func StrPtr(s *string) uintptr { 26 | return uintptr(unsafe.Pointer(s)) 27 | } 28 | func uintptrToMapS_I(maps *map[int][]byte) uintptr { 29 | return uintptr(unsafe.Pointer(maps)) 30 | } 31 | 32 | func uintptrToInterface(ptr uintptr) interface{} { 33 | return *(*interface{})(unsafe.Pointer(ptr)) 34 | } 35 | -------------------------------------------------------------------------------- /Public/public.go: -------------------------------------------------------------------------------- 1 | package public 2 | 3 | var Tmp = 0 4 | 5 | type TypeDLL struct { 6 | Is_Array bool 7 | Text string 8 | } 9 | 10 | type Type struct { 11 | Is_Array bool 12 | Text []byte 13 | } 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

GoLangLinkDLL

2 |
简介:在Windows使用go链接用go开发的DLL
3 | 4 | ## 开发背景 5 |
在原本的Go标准库中,是不支持之间使用go链接用go开发的DLL这在我们开发中带来了许多不便
6 |
此"框架/插件"致力于解决以下两个issues的问题
7 | 1.https://github.com/golang/go/issues/19282
8 | 2.https://github.com/golang/go/issues/22192 9 | 10 | ## 食用方法 11 |
可以直接测试/Demo中的实例DLL(./test.dll就来自/Demo中的实例)
12 | 13 | 1. 编译DLL(需要GCC以及开启CGO) 请注意public包,包位置自行修改 14 | ```shell 15 | go env -w GO111MODULE=auto 16 | go build -buildmode=c-shared -o test.dll ./ 17 | ``` 18 | 2. 测试程序 19 | ```go 20 | package main 21 | 22 | import ( 23 | "TestDLL/LoadDll" 24 | "TestDLL/Public" 25 | "fmt" 26 | ) 27 | 28 | func main() { 29 | Tmp := make(map[int]string) 30 | Tmp[0] = "123123" 31 | Tmp[1] = "你好" 32 | Open := load.OpenDLL("./test.dll") 33 | fmt.Println(Open.LoadFunc("Demo")(Tmp)) 34 | fmt.Println(Open.ReadConfig()) 35 | fmt.Println(public.Tmp) 36 | } 37 | 38 | ``` 39 | 3 运行 40 | ```shell 41 | go run test.go 42 | 43 | map[0:123123 1:你好] 44 | 你好 45 | 123123 46 | {false 你好} 47 | map[0:Demo] 48 | 0 //这里的0未修改,证明DLL是无法修改共享包中的全局变量 这点和Linux中的Plugin不一样 49 | ``` 50 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module TestDLL 2 | 3 | go 1.20 4 | -------------------------------------------------------------------------------- /test.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Linkangyis/GoLangLinkDLL/818a5b2268a7639cf93018fe8ebc69dbea3841e3/test.dll -------------------------------------------------------------------------------- /test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "TestDLL/LoadDll" 5 | "TestDLL/Public" 6 | "fmt" 7 | ) 8 | 9 | func main() { 10 | Tmp := make(map[int]string) 11 | Tmp[0] = "123123" 12 | Tmp[1] = "你好" 13 | Open := load.OpenDLL("./test.dll") 14 | fmt.Println(Open.LoadFunc("Demo")(Tmp)) 15 | fmt.Println(Open.ReadConfig()) 16 | fmt.Println(public.Tmp) 17 | } 18 | --------------------------------------------------------------------------------