Nim中如何向DLL外部函数传递可变长度数组?
Nim语言动态传递OpenAL alcCreateContext的属性数组
问题背景
在Nim中包装OpenAL32.dll时,alcCreateContext函数的attrlist参数要求接收指向ALCint数组的指针或nil。该数组采用[标志, 数值, 标志, 数值,...]的动态格式,长度随传入标志数量变化。现有代码硬编码了数组大小,无法灵活添加ALC_FREQUENCY这类额外标志,尝试openArray容器后,希望通过类型转换实现动态传递——这也是突破OpenAL默认256声音限制的关键方法。
原代码
when defined(windows): {.push cdecl, dynlib: "OpenAL32.dll", importc.} else: {.push importc.} type ALCint = cint ALCdevice* = pointer ALCcontext* = pointer const ALC_MONO_SOURCES* = 0x00001010 ALC_STEREO_SOURCES* = 0x00001011 ALC_FREQUENCY* = 0x00001007 proc alcCreateContext*(device: ALCdevice; attrlist: ptr array[0..3, ALCint]): ALCcontext proc alcOpenDevice*(devicename: cstring): ALCdevice const attributes = [ALC_MONO_SOURCES.ALCint, 65536.ALCint, ALC_STEREO_SOURCES.ALCint, 65536.ALCint] discard alcOpenDevice(nil).alcCreateContext(attributes.unsafeAddr)
解决方案
将alcCreateContext的attrlist参数类型替换为ptr UncheckedArray[ALCint],调用时通过cast将数组地址转换为该类型即可,这样就能支持任意长度的属性数组。
修改后的代码
when defined(windows): {.push cdecl, dynlib: "OpenAL32.dll", importc.} else: {.push importc.} type ALCint = cint ALCdevice* = pointer ALCcontext* = pointer const ALC_MONO_SOURCES* = 0x00001010 ALC_STEREO_SOURCES* = 0x00001011 ALC_FREQUENCY* = 0x00001007 proc alcCreateContext*(device: ALCdevice; attrlist: ptr UncheckedArray[ALCint]): ALCcontext proc alcOpenDevice*(devicename: cstring): ALCdevice const attributes = [ALC_MONO_SOURCES.ALCint, 65536.ALCint, ALC_STEREO_SOURCES.ALCint, 65536.ALCint] discard alcOpenDevice(nil).alcCreateContext(cast[ptr UncheckedArray[ALCint]](attributes.unsafeAddr))
内容的提问来源于stack exchange,提问作者Joshua Fenner
相关产品推荐
相关产品推荐

