I've built a thing like this for a project that had zero tolerance for any of C's well deserved faults, and yet, had to be written in C. I borrowed heavily from various other solutions (notably: Erlang) to ensure that the project was as safe as I could possibly make it. But I was always acutely aware that it only took one team member to declare a void * to an unbounded array for things to break out of that carefully constructed illusion of a safe jail.
Most of the work was done using some pretty tricky (and nifty!) macros and I really liked the end result, but I would have very much wished for that end result to be based on something more solid than C as the foundation. If you go down this route in the present day, unless you absolutely have to use something else. You'll be far happier and you will not have to be eternally vigilant against someone taking a shortcut.