Sign in to follow this  

Help with C/C++ interface for my language

This topic is 4380 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, I've been writing a lisp-derivative scripting language. I'm quite happy with the features (first-class closures, partial function evaluation, a class-based object system, other goofy stuff I wanted to try implementing). The C/C++ interface however is really unfriendly. Every lisp function accepts an argument list (an s-expression) and returns another s-expression. So right now the only functions I can bind in C++ must have the signature Expr* (*func) (Expr*). This is a hassle since I have to write wrapper functions around any existing function I want to bind. Any ideas on how to make a better interface? (it currently works like this)
Expr* plus_one(Expr* args)
{
   double val = first(args)->getValue();
   val += 1.0;
   return new Number(val);
}

int main()
{
   LispMachine lisp;
   lisp.BindFunction("++", &plus_one);
   Expr* result = lisp.run("(++ 2)");
   cout << result;
}

Thanks, Alex

Share this post


Link to post
Share on other sites
For your returns, you could provide automatic conversions from C++ Datatypes to your expressions. Your example would become


double plus_one(Expr* args)
{
double val = first(args)->getValue();
return val += 1.0;
}


You will need several versions of the "bind" method, one for every return type plus one for the "Expr*". Then you can put the user function in a wrapper.

Share this post


Link to post
Share on other sites
It might be way more than you want, but you should take some time and write a swig module for your language and create wrappers through it.

www.swig.org

It's not particulary difficult(there are already like 10 other modules to look at). I believe it will be time well spent.

Share this post


Link to post
Share on other sites
Gorg,
Thanks for directing me to SWIG. For now I want to spend most of my time adding language features. Once those are conrete I will probably make a swig module.

Steadtler,
I like the idea of automatic type conversions, since I already implement them internally within the language (expr->getValue(), expr->toString()). Thanks for the idea.

-Alex

Share this post


Link to post
Share on other sites
I'm posting this for the benefit of anyone else struggling to make a good C++ interface to a scripting language. I finally made something that allows most C++ functions to be hooked in to my lispish language with minimal effort.

Example:

int f1(int x, int y) { return x + y; }
string f2 (float num) { num += 0.9; return lexical_cast<string>(num); }

int main()
{
LispMachine lisp;
lisp.BindFunction("adder", f1);
lisp.BindFunction("other-func", f2);

Expr result = lisp.RunString("(other-func (adder 2 3))");
print(result); //prints "5.9"
return 0;
}



The trick to binding different C++ data types to wrap the function pointer in an ExternalFunction class, which does type conversion from standard C++ types to my language's types. To cover all the possible types and different numbers of arguments requires really ugly gobs of partial template specialization...but it works, and the end-user never has to see the ugly insides.

-Alex

Share this post


Link to post
Share on other sites

This topic is 4380 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this