Racket as scripting language in a game engine
Asked Answered
R

1

7

I would like to add scripting capabilities to my C++ game engine.

I have Engine.exe, Physics.dll, Audio.dll and I'm adding Scripting.dll which is a high-level Racket wrapper.

Engine.exe loads Physics.dll and sets up physics world, loads Audio.dll and sets up audio world. It is supposed to load Scripting.dll, to set up bindings to Physics.dll, Audio.dll and to load game scripts.

AFAIK there are two possible ways to embed Racket into a C++ program:

Using Foreign Interface seems bizarre due to necessity to load Physics.dll, Audio.dll two times: first from Engine.exe and then from the game script.

Writing Extensions looks more appealing, because it allows doing script bindings on C++ side. On the other hand you have to build your extension with raco ctool, link it with mzdyn object file — which looks awkward as well: why not make mzdyn a static library?

I would like to implement a single method, e.g. setupScriptBindings(), both in Physics.dll and in Audio.dll, and to call it from Engine.exe at the startup.

Is there a straightforward way to do it?

Remembrance answered 23/9, 2015 at 11:31 Comment(3)
Hm, maybe this description helps.Paper
Hm ... the links you provide talk about embedding C/other code into a Racket program. From you description, I think you want it the other way around, e.g. embedding Racket into your C++ application: docs.racket-lang.org/inside/embedding.html Though the easiest and probably cleanest solution would be to define some sort of protocol for controlling your game entities, and then start racket as a new process, communicating using sockets or some other IPC mechanism.Gravel
Offtopic: Racket has been successfully used in video game production by Naughty Dog. See «Racket on the Playstation 3» and «State-Based Scripting in Uncharted 2: Among Thieves».Remembrance
M
3

Having used both the extension and FFI methods of connecting Racket to C code, I have to say the FFI approach is much nicer. The bindings in Racket to the C functions are well specified and robust and dealing with C types in Racket is very nice. The only drawback to using the FFI approach is that, AFAIK, your Racket program must be the driver application.

With the embedding approach your C/C++ executable is the driver, but declaring the interface with the Racket code is much more manual and error prone. Not to mention that you have to either figure out raco ctool and replicate it or have racket's build system take over yours. For our purposes we wound up extracting the Racket sources and building it ourselves. I don't really recommend that approach.

Ultimately for my purposes having my application be a Racket application with a foreign .DLL/.so file that it loaded for C functions worked best, but it sounds like you may be stuck with the embedding approach.

Madai answered 24/9, 2015 at 18:39 Comment(3)
Thanks. Yes, I need an embedded solution. Though you say it might be tough, building Racket from source seems more appealing to me. If you could provide an example of «native» ↔ «script» binding from your embedding-based approach, it would be very helpful. What form of script execution did you choose: plain text, bytecode or standalone executable?Remembrance
We would use plain text or bytecode. Bytecode is noticeably faster, but you have to take care that it is updated or that Racket compiles it when necessary.Madai
And our native <-> script binding looked just like the example in the docs... nothing special.Madai

© 2022 - 2024 — McMap. All rights reserved.