1. How to wrap Arrays?
- Posted by Icy_Viking 1 month ago
- 928 views
Hi all,
How would I go about wrapping a variable that is decalred as an array?
BLARGG_EXPORT gme_err_t gme_play( Music_Emu*, int count, short out [] ); //notice that short out[]
2. Re: How to wrap Arrays?
- Posted by ghaberek (admin) 1 month ago
- 848 views
How would I go about wrapping a variable that is decalred as an array?
/* Generate 'count' 16-bit signed samples info 'out'. Output is in stereo. */ gme_err_t gme_play( Music_Emu*, int count, short out [] );
This is one of those "get" functions I mentioned the other day in SDL TTF 3 Issue.
Basically, out needs to be a block of memory that can hold count number of short values (signed 16-bit integer).
The programmer using the wrapper shouldn't be concerned about this; it should be part of the wrapping process.
Here's how to handle that:
- Allocate the memory you need to receive the data
- Pass that address as the out parameter
- If the call was successful (result = NULL) read the values with peek2s() -- peek 2-byte (16-bit) signed value(s)
- If the call failed, it is a pointer to a string (sounds weird, but I'll allow it)
- The value from #3 or #4 is your return result
Here's how I'd wrap that function:
public function gme_play(atom music_emu, integer count) -- allocate required memory atom out = allocate_data(sizeof(C_SHORT) * count) -- call the function object result = c_func(_gme_play, {music_emu,count,out}) if result = NULL then -- no error, peek the results result = peek2s({out, count}) end if free(out) -- release memory return result -- pointer to the error -- message or sequence of short values end function
It looks like gme_open_file() is similar, however, this is where things get tricky: how do we differentiate between a valid result and an error result? Both are non-zero atoms.
/* Create emulator and load game music file/data into it. Sets *out to new emulator. */ gme_err_t gme_open_file( const char path [], Music_Emu** out, int sample_rate );
Apparently, gme has a "last warning" concept but not a "last error" concept. We can add our our own functions to store return the last error.
-- placeholder for last error atom gme_last_error = NULL -- short wrapper for c_func() to clear/store last error. returns true (1) if no error -- message was returned, or false (0) if an error was stored. call gme_last_error() to -- get that value. note: only use this for gme functions that return error messages! function gme_func(integer id, sequence params) gme_last_error = c_func(id, params) return (gme_last_error = NULL) end function public function gme_error() return gme_last_error end function
Now we can wrap gme_open_file() like this:
public function gme_open_file(sequence path, integer sample_rate) -- allocate memory to hold a pointer atom out = allocate_data(sizeof(C_POINTER)) -- allocate string to memory atom ppath = allocate_string(path) -- prep the result atom result = NULL -- call the function with gme_func() to easily store the error if gme_func(_gme_open_file, {ppath,out,sample_rate}) then -- no error, peek the result result = peek_pointer(out) end if -- release memory free(ppath) free(out) return result -- handle of new emulator, or NULL if error -- occurred. call gme_last_error() for the error message. end function
And we can update our gme_play() wrapper like this:
public function gme_play(atom music_emu, integer count) -- allocate required memory atom out = allocate_data(sizeof(C_SHORT) * count) -- prep the result object result = NULL -- call the function with gme_func() to easily store the error if gme_func(_gme_play, {music_emu,count,out}) then -- no error, peek the results result = peek2s({out, count}) end if free(out) -- release memory return result -- sequence of short values, or NULL if error -- occurred. call gme_last_error() for the error message. end function
Hope that helps!
-Greg
P.S. There was no BLARGG_EXPORT in the libgme I was using for reference. Are we looking at different sources? Please link to your source when asking questions. A lot of context about "how" to wrap a library comes from the project and its documentation.
3. Re: How to wrap Arrays?
- Posted by Icy_Viking 1 month ago
- 840 views
Thanks Greg.
Helpful as always. Sorry about forgetting the source. Here is what I was referencing to.
https://github.com/libgme/game-music-emu/blob/master/gme/gme.h