2

I'm writing a game engine and I'd like to use Io for scripting. The engine is written in pure C99, not C++. I've successfully bound Io to some of the game's C functions, and it works well.
However, I'd like to call Io methods in the C game loop. Essentially, I'd like to load a script (probably with IoState_doFile_()) containing something along the lines of

Game init := method(...)
Game keypress := method(key, ...)
// and update, render, etc

Then, in the C game loop, I'd like to call those functions, some of which I need to pass arguments to. Unfortunately, Io's documentation is good but incredibly sparse. I've dug through the IoVM code a bit and have found nothing useful (I'm probably not digging hard enough). What's the best way to do this? Something like

sprintf(buf, "Game update(%u)", &deltaTime);
IoState_doCString_(buf);

seems rather hackish (assuming it even works; I haven't tried), not to mention probably really inefficient.

Peter C
  • 6,219
  • 1
  • 25
  • 37
  • see http://tech.groups.yahoo.com/group/iolanguage/message/4471 – Christoph Nov 09 '12 at 20:08
  • @Christoph You're a search ninja! (I tried the Yahoo group with no success.) Thanks a ton, that looks like exactly what I'm looking for. If you post it as an answer I'll accept it. – Peter C Nov 09 '12 at 20:45
  • @Christoph On second look, it seems that may only allow me to pass hardcoded arguments. I'll play around with it a bit and see if I can get this to work. – Peter C Nov 09 '12 at 20:54
  • @Christoph Never mind, I can (probably) use `IoMessage_setCachedArg_*` to use non-hardcoded arguments. Thanks so much! – Peter C Nov 09 '12 at 21:00
  • This actually works brilliantly. Thank you so much. I wish I could give you a ton of rep. – Peter C Nov 09 '12 at 21:38
  • I added an answer; feel free to add the code that worked for your particular case – Christoph Nov 09 '12 at 21:48

1 Answers1

1

According to this mailing-list thread, it is possible to use IoObject_rawDoString_label_() and IoState_retain_() to compile a message from source and apply it with IoMessage_locals_performOn_().

Alternatively, the message can be constructed manually via IoMessage_newWithName_() and the IoMessage_setCachedArg_*() functions.

I did not find any documentation for this, but the list of relevant functions can be found in IoMessage.h.

The code that works for this particular case is

/* When you initialize everything */
renderMessage = IoObject_rawDoString_label_(IoState_lobby(state),
    IoState_symbolWithCString_(state, "message(Game render())"),
    IoState_symbolWithCString_(state, "[Game render]"));
IoState_retain_(state, renderMessage);

/* In the game loop's render function */
IoMessage_locals_performOn_(renderMessage, IoState_lobby(state), IoState_lobby(state));

For messages that you need to pass arguments to, you need this instead:

/* When you initialize everything */
updateMessage = IoMessage_newWithName_(state, IoState_symbolWithCString_(state, "update"));
IoState_retain_(state, updateMessage);

/* In the game loop's update function */
IoMessage_setCachedArg_toInt_(updateMessage, 0, deltaTime);
IoMessage_locals_performOn_(updateMessage, IoState_lobby(state),
    IoObject_getSlot_(IoState_lobby(state), IoState_symbolWithCString_(state, "Game")));
Peter C
  • 6,219
  • 1
  • 25
  • 37
Christoph
  • 164,997
  • 36
  • 182
  • 240