1. How to wrap Arrays?

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[] 

new topic     » topic index » view message » categorize

2. Re: How to wrap Arrays?

Icy_Viking said...

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:

  1. Allocate the memory you need to receive the data
  2. Pass that address as the out parameter
  3. If the call was successful (result = NULL) read the values with peek2s() -- peek 2-byte (16-bit) signed value(s)
  4. If the call failed, it is a pointer to a string (sounds weird, but I'll allow it)
  5. 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.

new topic     » goto parent     » topic index » view message » categorize

3. Re: How to wrap Arrays?

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 

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu