# 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<

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()

}

```

![sdl.jpg](https://static.studygolang.com/190601/11584c5f5662ac24a2e4d91e0626dd01.jpg)

有疑问加站长微信联系(非本文作者))

c语言怎么调用sdl库函数,Go调用SDL2的C语言动态库相关推荐

  1. c语言程序如何调用标准库函数,如何调用C标准库的exit函数详解

    编译大于运算符 原定的计划中这一篇应当是要讲如何编译if表达式的,但是我发现没什么东西可以作为if的test-form的部分的表达式,所以觉得,要不还是先实现一下比较两个数字这样子的功能吧.说干就干, ...

  2. linux平台 使用dlopen接口调用HelloWorld动态库简单实例

    动态库(libxxx.so)一种调用方式是在编译的时候的时候指定库名 -lxxx,另一种调用方式是通过dlopen在程序里加载动态库,然后调用相关接口.相关接口比较简单,包括打开动态库,解析库里提供的 ...

  3. (成功案例超详细保姆级)vs2019 opencv qt创建动态库被C#调用

    之前有个项目关于图像处理,既用到了opencv,还二次开发了相机提供的动态库.一开始我是用QT写的,然后发现人家只需要我提供一个库函数调用就可以了,但是他是用C#写的.没办法,到处找资料,但是没有找到 ...

  4. 成功案例超详细-vs2019 opencv qt创建动态库被C#调用

    之前有个项目关于图像处理,既用到了opencv,还二次开发了相机提供的动态库.一开始我是用QT写的,然后发现人家只需要我提供一个库函数调用就可以了,但是他是用C#写的.没办法,到处找资料,但是没有找到 ...

  5. mac上用qt调用自己生成的qt动态库,该动态库又依赖第三方库

    qt下依赖于第三方库生成的动态库的调用 概述 基于声网的sdk如何在自己的动态库中使用 使用基于第三方库的动态库 下面看pro文件中的设置 概述 初次使用mac上的qtCreator生成动态库,该动态 ...

  6. Node.js使用ffi-napi,ref-array-napi,ref-struct-napi调用动态库

    0x01 概述 使用electron开进行桌面程序的开发,似乎成了WEB前端开发人员转桌面程序开发的首选.近期有一些使用在electron中使用加密锁的需求,学习了一下在Node.js中通过ffi-n ...

  7. c语言调用c 的库,C语言程序调用C库函数方法

    C语言程序调用C 库函数方法,关键是函数名字解析问题. 其实实现起来不是很难. 使用关键字 extern \"C\" 可以使得C 编译器生成的函数名满足C语言的要求 例子如下: 链 ...

  8. 如何通过JNI在Java中调用C库函数

    使用Java语言进行开发时,可能由于处理速度.硬件控制或者复用既有的C/C++模块等方面的原因,需要Java层与使用C/C++编写的应用.模块或库进行交互,共同完成某些任务.在两者之间充当连接桥梁作用 ...

  9. 正确理解以下名词及其含义:(1)源程序,目标程序,可执行程序(2)程序编辑,程序编译,程序连接(3)程序,程序模块,程序文件 (4)函数,主函数,被调用函数,库函数

    正确理解以下名词及其含义: (1)源程序,目标程序,可执行程序. ​ 源程序:指未编译的按照一定的程序设计语言规范书写的文本文件,是一系列人类可读的计算机语言指令 ​ 目标程序:为源程序经编译可直接被 ...

最新文章

  1. python性能分析
  2. Colored Sticks--POJ 2513
  3. Android:SharedPreferences详解+示例
  4. [转载] 向集合中添加自定义类型--建议在自定义类型的时候要重写equals方法
  5. 卸载驱动出现:rmmod: can't change directory to '/lib/modules': No such file or directory
  6. PHP几种常见魔术方法与魔术变量解析 1
  7. 处理 TXT 文本技巧
  8. JAVA环境变量的设置及修改
  9. 不要把敏感信息写在k8s的env上
  10. matlab fisher z变换,关于GCA统计
  11. 如何在线查询学历证书
  12. 基于ASAM ODS标准的试验数字化平台-WDP
  13. 计算机网络按分布范围分类可分为局域网,计算机网络按照覆盖范围可以分为局域网...
  14. 微信消息记录导出并制作图云(安卓版)
  15. 有一架天平12个小球,其中有11个重量相同,1个与另外11个不同(不清楚这个球是轻还是重),要求最多称3次,就可以将其中重量特殊的小球找出来。
  16. 顺序栈—栈顶指针的两种初始化
  17. 【故障诊断分析】基于matlab BP神经网络三相逆变器故障诊断研究【含Matlab源码 1736期】
  18. 震惊了!130万研究生报名用户的数据遭泄露
  19. ps中背景橡皮擦抠图方法
  20. 《20几岁要应用的经济学智慧》经济知识四

热门文章

  1. java如果是晴天如果是男人_三、没有测光表时的曝光:“晴天 f/16”法则(转自 色影无忌)...
  2. android2.3.5中阿拉伯文字符显示顺序不是从右至左显示
  3. VMware Station pro15虚拟机的下载与安装
  4. 苹果手机投影_智能手机投屏到投影仪
  5. 爱酱,鹿鸣?!自己怎么做一个虚拟二次元偶像?
  6. android指南针校准 代码_android 指南针app源码(亲测可用)
  7. 嵌入式之uboot源码分析-启动第一阶段学习笔记
  8. [NOI2016] 优秀的拆分 题解
  9. 武汉市服务业领军企业认定条件、流程及申报政策奖励补贴标准
  10. APICLOUD实现沉浸式导航栏在Android和ios上的兼容