内容简介:在网上找到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 包跨语言远程调用
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
游戏数据分析的艺术
于洋、余敏雄、吴娜、师胜柱 / 机械工业出版社 / 2015-7 / 79.00
《游戏数据分析的艺术》是中国游戏产业的开创性著作,具有里程碑意义,它首次系统讲解了如何对游戏行业的数据进行分析,在行业里竖起了一根标杆。作者是来自TalkingData等国内顶尖的数据分析机构和西山居这样的知名游戏公司的资深数据分析专家, 对游戏数据从不同的业务角度进行了诠释。本书详细剖析了游戏数据分析相关的指标、方法论、内容挖掘、数据挖掘、软件使用、游戏设计、运营策划、渠道推广、收入解读、用户分......一起来看看 《游戏数据分析的艺术》 这本书的介绍吧!