Bellow is a minimal example when wrapping the OpenAL32.dll. The foreign function alcCreateContext
has the argument attrlist
which takes a ptr
to an array of type ALCint
or nil
. The issue is the array can be of different lengths depending on the amount of different flags passed in. The array should be organized as [flag, int, flag, int, ...]. How can this be accomplished in a more dynamic way allowing the inclusion of ALC_FREQUENCY
for example? The array size is currently hard coded into the procedure and its nasty.
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)
I experimented with openArray
and other containers. Is the solution some sort of cast
? This is also the workaround for getting more then 256 sounds out of OpenAL.
Answer from PMunch. Thank You.
The foreign function now wants ptr UncheckedArray[ALCint]
and when passing the argument use cast[ptr UncheckedArray[ALCint]](attributes.unsafeAddr)
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))
CodePudding user response:
An array in C is simply a pointer to anywhere with one or more contiguous elements of the same type. So to pass a C array to a function you simply need to get such a pointer. Say for example you have a seq
of integers then the address of the first element is a C array. Simply do mySeq[0].addr
and you're good. Keep the lifecycle of the data in mind though. If Nim doesn't find any more references to the sequence then the memory will get freed. You can also manually get a pointer with create
(https://nim-lang.org/docs/system.html#create,typedesc) and you can cast such pointers to ptr UncheckedArray[T]
to be able to use [] on the data in Nim.