I am trying to create an architecture that would use C/C++ as “scripting language”. I already have a prototype working based on:
http://www.codeproject.com/Articles/29999/Compiling-C-code-at-runtime
and
http://runtimecompiledcplusplus.blogspot.com
My prototype allows me to recompile a dynamic link library / shared object and reload it at runtime. I only have a small problem lets take in example the following code:
[ bot.c ]
typedef struct
{
float health;
float speed;
bool alive;
} Bot;
Bot bot = { .health = 100.0f,
.speed = 1.0f,
.alive = true };
void OnCollision( void )
{
bot.health -= 10.0f;
if( bot.health <= 0.0f )
{ bot.alive = false; }
}
void OnUpdate( void )
{
if( bot.alive )
{
/* Update animation */
}
}
If the bot.c script is assigned to 1 bot its ok, but if I assign the callbacks to multiple bots they share the same data (1 get hit, they all get hit!). How can run the bot script “separately” for each bots?
I already research on coroutine in C/C++ (using setjmp/longjmp) but its risky for C++ constructors & destructors (and also force you to integrate macros inside your functions, which in my case is not an options for my users).
I was thinking about running multiple threads, but the same problem will occur (since the data comes from a dll/so it is shared). Im not too familiar with fork/co-process but it does not seems to apply for my case. And I do not think that pipes are an option as well… Im pretty much stuck.
Is there anyway to solve this problem?
ps: Yes I know that scripting language like Lua or Javascript (V8) have built-in coroutine or in the case of Lua lua_thread that would fix my issue but I want to stick with a C/C++ interface for the users to code since its for gaming performance is critical!
You don’t need anything like coroutines. The problem is that you have a single global variable holding the data and you simply need multiple instances of it.
Now the standard shared library machinery won’t allow you to duplicate the static data of the module, but you don’t need to. Just don’t allocate the data statically, but create multiple instances of it.
In C++ it would be easier to use, but somewhat more difficult to implement since you’d need to compute the mangled symbol names and correct incantation to do new and delete. The script would simply look like:
You’d need to know the class name, but that could be derived from the module name or something like that.
You could write a template that would generate bunch of static functions to somewhat portably handle the initialization. Like:
used like
at the end of the “script”. Than you just look that symbol up and call the function pointers in it.
In C it would be more difficult to use, because you’d need to explicitly write init and deinit functions, but you already know how to call it:
In either case you simply create any number of instances, either with
operator new[]andBotconstructor or withInitand call the functions/methods with appropriate argument.