Scripting Languages and C++

Contents

C++ programmers often praise their statically typed language. Having a compilation phase with the possibility to statically check for possible errors is a feature that makes good for the time we have to wait for the compiler to do its job. Some would never ever touch a scripting language. They are at fault, and here is why.

What is a scripting language?

“Scripting language” is an often used loose term for interpreted and usually dynamically typed languages. While some of the are precompiled when a piece of code is loaded, the gist is that many of the errors that would be caught by the compiler in C++ are runtime errors in those languages.

Dynamic typing makes things worse: variables in those languages usually don’t have a fixed type, so you can assign a string to a variable that was an integer before, and later give it a value of yet another type. If you are used to the rigid static typing of C++ this sounds like a nightmare.

Why use a scripting language then?

Those weaknesses of scripting languages can be strengths, too. The lack of a compile phase makes development much faster. The development cycle is just “type, run tests” instead of “type, compile, run tests”.

Dynamic typing means that we can achieve polymorphism without the need to define a class hierarchy. Classes and objects only have to provide an interface that is used by a function, they don’t need to be derived from a certain base class. Take for example this Python function:

def print_sum(a, b):
    print(a + b)

This function will just work for any two objects `a` and `b` for which the `+` operator is defined and has a result that is printable. It works pretty much like compile time polymorphism in C++ – without the compile time:

template <class T, class U> 
void print_sum(T const& t, U const& u) { 
  std::cout << t+u << '\n'; 
}

In some languages we can even add the needed interface on the go to existing objects. When functions are just objects and objects are open for extension, we can add a new attribute to an object that is a function.

var a = {};
a.say_hello = function() { 
  console.log("hello");
}
a.say_hello();

Choosing a language is a tradeoff. In larger programs we typically want to have more safety and less error prone code, so we accept the longer development times associated with statically typed and compiled languages. Shorter and manageable tasks can be done quicker with a scripting language.

Performance

Many people use C++ because they care for performance. Interpreted languages don’t have the same potential performance, but they can come pretty close. They can have sophisticated optimizing just-in-time compilers that emit effective byte code.

As always when it comes to performance, to measure and compare is better than to follow a hunch. The performance difference between some interpreted scripting language byte code and compiled C++ code without profiler guided manual optimization may be negligible.

Mix scripting languages and C++

There are different ways to mix C++ and scripting languages. Some of those languages have the ability to call C code and therefore C++ functions that are declared `extern “C”`. Others come with direct bindings to C++.

That way we can call C++ code from a scripting language, using the scripting language as glue code. Typically we would leave complex or performance sensitive subtasks to C++ and do the rest in another language. This approach is more and more used in scientific computing.

The other way round is embedding a scripting language into a C++ application. Scripting language interpreters are often written in C or C++ and can therefore easily be linked into a C++ program. We can provide an API to give the script controlled access to our C++ objects.

This approach can be used to make parts of our application freely configurable. We can even give our users a full scripting console where they can hack away as they like. We’d better check twice how much access we give them to our application innards that way.

Related to the latter approach is the possibility to write the GUI for our C++ application in another language. C++ isn’t particularly known for a standardized, rich and easy to handle GUI framework. In addition, GUIs are usually not very performance sensitive and overly complex either.

An example for GUIs written in scripting languages is a HTML/CSS GUI displayed in a browser window powered by JavaScript that directly interoperates with C++ as backend. In my old days as World of Warcraft addict I used to rearrange and rewrite my complete UI with Lua.

Conclusion

Scripting languages are just another addition to our toolbox. We should at least master one or two of them to not treat every problem nail with our C++ sledge hammer. I will write a bit more about scripting languages next week.

Previous Post
Next Post

7 Comments


  1. Embedding a C++ style scripting language (AngleScript for example http://www.angelcode.com/angelscript/) in a C++ application can lead to huge benefits. It’s a win win situation because you have the flexibility of a script with the performance of C++ in the back end. Game developers have been doing this for years.

    Reply

  2. I personally advocate against scripting languages and platform. from ny observation, usually projects are built fast with scripting languages at first, and the time to market is fast, but after few cycles of development where you project becomes big and heavy than the ugly side of scripting language shows itself.

    basically, after spending much time with javascript developers, a quit precentage of their time is spent over silly stuff like debuginng silly mistakes like “undefined is not a function” etc.

    so yeah, building a small project with JS/PHP/Python is quick and easy. I don’t think a scripting language can hold if you’re bulding a huge long lasting project.

    I think that the problem with C++ is not language itself, but the lack of good , open source tools, libraries and platform.
    basically everything we have now is either paid , either old , either really not performant, either complicated, either not working. I think that as a comunity , the best thing we we can do to make our productivity better is to develop these libraries instead of waiting for the standard to standarize them, or settle for different programing language.

    Reply

    1. Hi David, thanks for your thoughts.
      Just to be clear, I am by no means proposing to abandon C++ for a scripting language, and neither do I think writing large applications solely in a scripting language is a good idea. I touched that in the part where I talk about the tradeoffs, and that scripting languages are good for small tasks and that of course we should rely on the type safety etc. of a compiled language when it comes to bigger applications.

      This post is definitely not about shunning C++ (I’d be a pretty bad C++ blogger if it was, right?) – it’s about that other tool in the tool box that so many developers of compiled languages neglect. There really is no point in whipping up a big C++ application when all you need are 10 lines of Python.

      Reply

  3. Great article, thank you. Scripting has been in the news lately in C++ circles. I’ve been struggling to understand why I would want to use scripting when I could just as easily use C++ instead. Your two use-cases of giving user access to C++ objects and providing a GUI frontend to a C++ backend are useful in this regard. I’d really like to see occasional followup posts on scripting.

    Reply

    1. Same with me too…confusion resolved…kudos to the author. His articles are all very useful which solves these riddles of a confused mind.

      Reply

  4. Nice post. I agree that scripting languages can be very useful, but using C++ doesn’t necessarily mean a lot of waiting to compile your code. When I’m writing most of my C++ code, my compile times are less than a second because I’m only compiling and testing the component that I’m working on. I think this can be done regardless of the overall size of the code base.

    Reply

    1. I agree that it’s normally not a big impediment, but occasionally you run into refactoring that affects more than a few translation units. I have seen legacy code where it was not uncommon to have a 40 minute compile several times a week.
      On continuous integration or at least nightly builds you should do a clean build which can easily last hours in larger projects.

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *