内容简介:在网上找到go的GUI项目基本都需要安装额外软件库,尝试了一下使用go调用dll库的,有所收获,抛砖引玉,留个记录怕以后忘了。
Go调用SDL2的 C语言 动态库
在网上找到 go 的GUI项目基本都需要安装额外软件库,尝试了一下使用go调用dll库的,有所收获,抛砖引玉,留个记录怕以后忘了。
1.目录结构
└─libtest │ main.go │ sdl.go └─ lib SDL2.dll
2. 库函数封装(sdl.go)
package main import ( "syscall" "unsafe" ) //SDL_INIT_Flag 初始化标志 const ( SDL_INIT_TIMER = 0x00000001 SDL_INIT_AUDIO = 0x00000010 SDL_INIT_VIDEO = 0x00000020 /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ SDL_INIT_JOYSTICK = 0x00000200 /**< SDL_INIT_JOYSTICK implies SDL_INIT_EVENTS */ SDL_INIT_HAPTIC = 0x00001000 SDL_INIT_GAMECONTROLLER = 0x00002000 /**< SDL_INIT_GAMECONTROLLER implies SDL_INIT_JOYSTICK */ SDL_INIT_EVENTS = 0x00004000 SDL_INIT_NOPARACHUTE = 0x00100000 /**< compatibility; this flag is ignored. */ SDL_INIT_EVERYTHING = SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER ) // SDL_WindowFlags 窗体标志 const ( /* !!! FIXME: change this to name = (1<<x). */ SDL_WINDOW_FULLSCREEN = 0x00000001 /**< fullscreen window */ SDL_WINDOW_OPENGL = 0x00000002 /**< window usable with OpenGL context */ SDL_WINDOW_SHOWN = 0x00000004 /**< window is visible */ SDL_WINDOW_HIDDEN = 0x00000008 /**< window is not visible */ SDL_WINDOW_BORDERLESS = 0x00000010 /**< no window decoration */ SDL_WINDOW_RESIZABLE = 0x00000020 /**< window can be resized */ SDL_WINDOW_MINIMIZED = 0x00000040 /**< window is minimized */ SDL_WINDOW_MAXIMIZED = 0x00000080 /**< window is maximized */ SDL_WINDOW_INPUT_GRABBED = 0x00000100 /**< window has grabbed input focus */ SDL_WINDOW_INPUT_FOCUS = 0x00000200 /**< window has input focus */ SDL_WINDOW_MOUSE_FOCUS = 0x00000400 /**< window has mouse focus */ SDL_WINDOW_FULLSCREEN_DESKTOP = (SDL_WINDOW_FULLSCREEN | 0x00001000) SDL_WINDOW_FOREIGN = 0x00000800 /**< window not created by SDL */ SDL_WINDOW_ALLOW_HIGHDPI = 0x00002000 /**< window should be created in high-DPI mode if supported. On macOS NSHighResolutionCapable must be set true in the application's Info.plist for this to have any effect. */ SDL_WINDOW_MOUSE_CAPTURE = 0x00004000 /**< window has mouse captured (unrelated to INPUT_GRABBED) */ SDL_WINDOW_ALWAYS_ON_TOP = 0x00008000 /**< window should always be above others */ SDL_WINDOW_SKIP_TASKBAR = 0x00010000 /**< window should not be added to the taskbar */ SDL_WINDOW_UTILITY = 0x00020000 /**< window should be treated as a utility window */ SDL_WINDOW_TOOLTIP = 0x00040000 /**< window should be treated as a tooltip */ SDL_WINDOW_POPUP_MENU = 0x00080000 /**< window should be treated as a popup menu */ SDL_WINDOW_VULKAN = 0x10000000 /**< window usable for Vulkan surface */ ) // SDL_Window SDL窗体 type SDL_Window struct{} // SDL_Event SDL 事件 type SDL_Event struct{} // SDL_Init SDL 初始化 func SDL_Init(flags uint32) bool { ret := SysCallDll("SDL_Init", 1, uintptr(flags)) if int(ret) == 0 { return true } return false } // SDL_CreateWindow 创建window窗体,失败返回nil func SDL_CreateWindow(title string, posX, posY, width, height, sdlWindowFlag int32) *SDL_Window { var tp, _ = syscall.BytePtrFromString(title) // 将string转为*byte var tptr = unsafe.Pointer(tp) // 获取*byte指针 ret := SysCallDll("SDL_CreateWindow", 6, uintptr(tptr), uintptr(posX), uintptr(posY), uintptr(width), uintptr(height), uintptr(sdlWindowFlag)) if int(ret) == 0 { return nil } return (*SDL_Window)(unsafe.Pointer(ret)) } // SDL_Delay 延迟xxx ms后返回 func SDL_Delay(ms uint32) { SysCallDll("SDL_Delay", 1, uintptr(ms)) } // SDL_DestroyWindow 销毁窗体 func SDL_DestroyWindow(window *SDL_Window) { SysCallDll("SDL_DestroyWindow", 1, uintptr(unsafe.Pointer(window))) } //SDL_Quit(void) 退出SDL系统 func SDL_Quit() { SysCallDll("SDL_Quit", 0) } // SDL_PollEvent 轮询当前挂起的事件 func SDL_PollEvent(event *SDL_Event) bool { ret := SysCallDll("SDL_PollEvent", 1, uintptr(unsafe.Pointer(event))) if int(ret) == 1 { return true } return false }
3. 加载动态库(main.go)
package main import ( "fmt" "syscall" "unsafe" ) // ThrowErr 抛出异常 func ThrowErr(str string, err error) { if err != nil { fmt.Printf("[Err]:%s,%v\n", str, err) } } // 动态库的指针 var hsdl syscall.Handle // LoadDLL 加载动态库 func LoadDll() { var err error hsdl, err = syscall.LoadLibrary("lib/SDL2.dll") ThrowErr("LoadLibrary-SDL", err) } // FreeDll 释放动态库 func FreeDll() { if hsdl != 0 { syscall.FreeLibrary(hsdl) } } // SysCallDll 包装syscall.Syscall/6/9/12 调用动态库内函数 // funcName 函数名; argsNum 参数个数; args 可变参数 func SysCallDll(funcName string, argsNum int32, args ...uintptr) (r uintptr) { proc, err := syscall.GetProcAddress(hsdl, funcName) ThrowErr(funcName, err) var errs error var debug bool = false var fargs = [12]uintptr{} //获取参数 for i, arg := range args { fargs[i] = arg } if (argsNum > -1) && (argsNum < 4) { //小于等于3个参数 r, _, errs = syscall.Syscall(uintptr(proc), uintptr(argsNum), fargs[0], fargs[1], fargs[2]) //ThrowErr(funcName, errs) } else if (argsNum > 3) && (argsNum < 7) { //小于等于6个参数 r, _, errs = syscall.Syscall6(uintptr(proc), uintptr(argsNum), fargs[0], fargs[1], fargs[2], fargs[3], fargs[4], fargs[5]) //ThrowErr(funcName, errs) } else if (argsNum > 6) && (argsNum < 10) { //小于等于9个参数 r, _, errs = syscall.Syscall9(uintptr(proc), uintptr(argsNum), fargs[0], fargs[1], fargs[2], fargs[3], fargs[4], fargs[5], fargs[6], fargs[7], fargs[8]) //ThrowErr(funcName, errs) } else if (argsNum > 9) && (argsNum < 13) { //小于等于12个参数 r, _, errs = syscall.Syscall12(uintptr(proc), uintptr(argsNum), fargs[0], fargs[1], fargs[2], fargs[3], fargs[4], fargs[5], fargs[6], fargs[7], fargs[8], fargs[9], fargs[10], fargs[11]) //ThrowErr(funcName, errs) } else { fmt.Println("The args number was bigger than 12.") } if debug { fmt.Println(errs) } return r } // CharPtr2String 从char指针读取string func CharPtr2String(vcode uintptr) string { var vbyte []byte for i := 0; i < 20; i++ { sbyte := *((*byte)(unsafe.Pointer(vcode))) if sbyte == 0 { break } vbyte = append(vbyte, sbyte) vcode += 1 } return string(vbyte) } // testSdlWindow 创建窗体,然后暂停程序所以窗体没响应 func testSdlWindow() { LoadDll() // 加载动态库 if SDL_Init(SDL_INIT_VIDEO) { // 初始化视频子系统 // 创建窗体 win := SDL_CreateWindow("SDL窗体标题", 50, 50, 600, 480, SDL_WINDOW_SHOWN) if win == nil { fmt.Println("SDL_CreateWindow 失败") } SDL_Delay(6000) // 暂停程序6000ms SDL_DestroyWindow(win) // 销毁释放窗体 } SDL_Quit() // 退出清理SDL defer FreeDll() // 释放动态库SDL2.dll } // testSdlWindow2 创建窗体,使用事件循环显示可响应窗体 func testSdlWindow2() { LoadDll() // 加载动态库 if SDL_Init(SDL_INIT_VIDEO) { // 初始化视频子系统 // 创建窗体 win := SDL_CreateWindow("SDL窗体标题", 50, 50, 600, 480, SDL_WINDOW_SHOWN) if win == nil { fmt.Println("SDL_CreateWindow 失败") } for { // 事件循环 if SDL_PollEvent(evt) { // 轮询事件队列 // 此处SDL_Event在C语言中为联合,需要其他处理 // if GetEventType(evt) == SDL_QUIT { // 退出事件 // break // } } } SDL_DestroyWindow(win) // 销毁释放窗体 SDL_Quit() // 退出清理SDL defer FreeDll() // 释放动态库SDL2.dll } } var evt = new(SDL_Event) // SDL事件 func main() { testSdlWindow2() }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Go语言反射之反射调用
- golang之调用C语言代码
- Go语言调用-Physx物理引擎
- C语言实现GET请求调用API
- thrift 增加跨语言的调用链【TODO】
- Golang 语言使用标准库 net/rpc/jsonrpc 包跨语言远程调用
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Inside Larry's and Sergey's Brain
Richard Brandt / Portfolio / 17 Sep 2009 / USD 24.95
You’ve used their products. You’ve heard about their skyrocketing wealth and “don’t be evil” business motto. But how much do you really know about Google’s founders, Larry Page and Sergey Brin? Inside......一起来看看 《Inside Larry's and Sergey's Brain》 这本书的介绍吧!