golang调用sdl2,播放pcm音频,报错signal arrived during external code execution。
golang调用sdl2,播放pcm音频,报错signal arrived during external code execution。
win10 x64下测试成功,其他操作系统下不保证成功。
采用的是syscall方式,不是cgo方式。
见地址
在go1.16.15编译后然后执行,会报如下错。换成go1.18就不报错了。
Exception 0xc0000005 0x0 0xc000442000 0x7ff96da8db50
PC=0x7ff96da8db50
signal arrived during external code execution
syscall.Syscall6(0x7ff96daa7440, 0x4, 0x20d6354a0a0, 0xc000442000, 0x1000, 0x10, 0x0, 0x0, 0x0, 0x0, …)
D:/Program Files/Go/go1.16.15/src/runtime/syscall_windows.go:347 +0xf2
syscall.(*Proc).Call(0xc000599b40, 0xc0001207c0, 0x4, 0x4, 0x20, 0xa6ffa0, 0x20d6354a001, 0xc0001207c0)
D:/Program Files/Go/go1.16.15/src/syscall/dll_windows.go:188 +0x385
syscall.(*LazyProc).Call(0xc00007fc50, 0xc0001207c0, 0x4, 0x4, 0x3, 0x3, 0x20d6354a0a0, 0x0)
D:/Program Files/Go/go1.16.15/src/syscall/dll_windows.go:339 +0x78
github.com/moonfdd/sdl2-go/sdl.SDL_MixAudio(0x20d6354a0a0, 0xc000442000, 0x1000001000)
D:/mysetup/gopath/src/sdl2-go/sdl/SDL_audio.go:1185 +0xf1
main.fill_audio_pcm(0xc00010ff48, 0x20d6354a0a0, 0x1000, 0x0)
D:/mysetup/gopath/src/sdl2-go/examples/a06-sdl-pcm/main1.go:33 +0x125
goroutine 1 [chan receive]:
main.main()
D:/mysetup/gopath/src/sdl2-go/examples/a06-sdl-pcm/main1.go:66 +0x288
rax 0x20d6354a0a0
rbx 0xc0000086e0
rcx 0x20d6354a0a0
rdi 0xecaa4c3000
rsi 0xc0000439c0
rbp 0xc000043960
rsp 0xecabbffb50
r8 0x8010
r9 0x20d6354b0a0
r10 0x10
r11 0x4
r12 0xa7b800
r13 0x0
r14 0x0
r15 0x2030001
rip 0x7ff96da8db50
rflags 0x10206
cs 0x33
fs 0x53
gs 0x2b
golang代码如下:
package main
import (
"fmt"
"github.com/moonfdd/sdl2-go/sdl"
"github.com/moonfdd/sdl2-go/sdlcommon"
"io/ioutil"
"sync"
"syscall"
"unsafe"
)
var o sync.Once
//音频设备回调函数
func fill_audio_pcm(udata sdlcommon.FVoidP, stream *sdlcommon.FUint8T, len1 sdlcommon.FInt) uintptr {
info := (*Info)(unsafe.Pointer(udata))
if info.isStop {
return 0
}
if info.Start >= info.Len {
info.isStop = true
o.Do(func() {
ch <- struct{}{}
})
return 0
}
sdl.SDL_memset(uintptr(unsafe.Pointer(stream)), 0, uint64(len1))
if len1 > int32(info.Len-info.Start) {
fmt.Println("不足len", len1, info.Len-info.Start)
len1 = int32(info.Len - info.Start)
}
sdl.SDL_MixAudio(stream, &info.Data[info.Start], uint32(len1), sdl.SDL_MIX_MAXVOLUME/8)
info.Start += int(len1)
return 0
}
var ch = make(chan struct{}, 1)
func main() {
sdlcommon.SetSDL2Path("SDL2.dll")
var spec sdl.SDL_AudioSpec
sdl.SDL_Init(sdl.SDL_INIT_AUDIO)
spec.Freq = 44100
spec.Format = sdl.AUDIO_S16SYS // 采样点格式
spec.Channels = 2 // 2通道
spec.Silence = 0
spec.Userdata = uintptr(0)
spec.Samples = 1024 // 23.2ms -> 46.4ms 每次读取的采样数量,多久产生一次回调和 samples
spec.Callback = syscall.NewCallback(fill_audio_pcm) // 回调函数
fileData, err := ioutil.ReadFile("44100_16bit_2ch.pcm")
if err != nil {
fmt.Println("读取文件失败", err)
return
}
info := new(Info)
info.Data = fileData
info.Len = len(fileData)
spec.Userdata = uintptr(unsafe.Pointer(info))
if sdl.SDL_OpenAudio(&spec, nil) != 0 {
fmt.Println("打开音频设备失败")
return
}
sdl.SDL_PauseAudio(0)
<-ch
fmt.Println("关闭")
sdl.SDL_CloseAudio()
sdl.SDL_Quit()
}
type Info struct {
Data []byte
Len int
Start int
isStop bool
}
执行结果如下:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
2021-06-21 2021-06-21:贩卖机只支持硬币支付,且收退都只支持10 ,50,100三种面额。一次购买只能出一瓶可乐,且投钱和找零都遵循优先使用大钱的原则,需要购买的可乐数量是m, 其中手头拥有的10、50