You cannot do that because some languages implementations could have an ABI different and incompatible with the C one.
On current systems, C is very common and most (but not all) language implementations have an ABI and calling conventions compatible with the one from C. Notice that it is a property of the implementation (your C compiler and your operating system), not of the programming language.
Also, some languages have different and incompatible views on control flow (look into call/cc and tail-calls in Scheme, Goroutines in Go, or backtracking and cut operator in Prolog, CLIPS rules, concurrent actor languages, ....). I'm not sure you'll be able to design something which easily fits all of them.
If using C++, beware of name mangling and of exception handling. (e.g. C longjmp
is not friendly with C++ exceptions). Dynamic loading facilities like dlopen
and dlsym
are relevant to name mangling. So prefer an API using extern "C"
functions. libgccjit could be inspirational (it is coded in C++ but has a C friendly API) and perhaps useful (you could consider runtime generation of glue code).
Memory management (notably with garbage collection) is also an issue. Study for examples foreign function interface of Ocaml and of SBCL and of Lua and of Guile. Look into libffi.
You could provide some reflection facilities (e.g an API to query your API, e.g. like GTK introspection). You might try to provide a generic closure mechanism like in GObject-s.
You could use (or customize or adapt) code generators like SWIG. You might consider compiler plugins (e.g. GCC MELT extensions).
There is no silver bullet.
NB. Better make your stuff free software. You might get outside contributions and you'll need outside help to interface your thing with many programming languages, including some that you don't even know. Open source is a good way to counter leaky abstractions (since you and other contributors can dive into the implementation source code). Given the variety of programming languages, you will need outside help.