Description

ofxLua is an Open Frameworks addon for running a Lua embedded scripting interpreter within an OpenFrameworks application. Using the SWIG (Simple Wrapper and Interface Generator) tool, C++ functions and classes can be bound to the Lua api allowing them to be called within a Lua script. This is useful in separating the upper level logic from the lower level application and is utilized in numerous video games and applications.

In addition, ofxLua provides bindings for the OpenFrameworks API.

Lua combines simple procedural syntax with powerful data description constructs based on associative arrays and extensible semantics. Lua is dynamically typed, runs by interpreting bytecode for a register-based virtual machine, and has automatic memory management with incremental garbage collection, making it ideal for configuration, scripting, and rapid prototyping.

SWIG is a software development tool that connects programs written in C and C++ with a variety of high-level programming languages. It is used to generate the C++ bindings which wrap the OpenFrameworks API for Lua.

(Optional) LuaJIT is a Just-In-Time Compiler (JIT) for the Lua programming language. It implements the Lua API but is optimized for performance over the standard Lua distribution. It is recommended to use LuaJIT when speed is a concern and it is enabled on embedded Linux in addon_config.mk for this reason.

OpenFrameworks is a cross platform open source toolkit for creative coding in C++

Why not Javascript?

Those coming from a Javascript background may ask "Why Lua? Why not Javascript? I like Javascript!"

Lua has a long history of use as a embedded scripting language and, as such, is both smaller & much easier to embed on pretty much every platform. The compiled language adds less than 500kb to your app binary versus many Mbs for Javascript or Python. Speed-wise, the base Lua interpreter is oftentimes faster than either language due to it's simplicity and using LuaJIT may add a speed increase of many orders of magnitude. As an embedded language, Lua makes it relatively easy to bind C/C++ functions & objects to it's scripting environment.

For these reasons, Lua has been used for game development for many years:

Those coming from an embedded computing or game development background are probably familiar with Lua while those coming from a design and/or web development are used to Javascript. In many ways, both languages share a number of similarities and the rest is due to simple syntax or design differences. When it comes down to it, no one language or environment is better than another, they just have different focuses and design backgrounds. Do not dismiss Lua because you are unfamiliar with it as not every nail needs the same hammer.

Currently, ofxLua is being developed on Mac OSX and has been tested on OSX, iOS, & Linux. Windows and Android should work but have not been tested.

Installation and Build

Place ofxLua within a folder in the apps folder of the OF dir tree:

openframeworks/addons/ofxLua

Which version to use?

If you are using a stable version (0062, 007, ...) of OpenFrameworks then you want to use a git tag of ofxLua for that version. You can select the tag in the Github "Current Branch" menu or clone and check it out using git.

For example, the following commands will clone ofxLua and switch to the OF 0062 tagged version:

The master branch of ofxLua will work with the current stable version of OpenFrameworks and can be considered relatively stable.

You'll need to checkout the swig-openframeworks submodule as well using:

git submodule init
git submodule update

Dependencies

For embedded Linux (arm, Raspberry Pi, etc), LuaJIT is used for better performance. Make sure you have the luajit-5.1 development package installed.

Running the Example Projects

The example projects are in the luaExample & luaExampleIOS folders.

Project files for the examples are not included so you will need to generate the project files for your operating system and development environment using the OF ProjectGenerator which is included with the OpenFrameworks distribution.

To (re)generate project files for an existing project:

click the "Import" button in the ProjectGenerator

navigate the to base folder for the project ie. "luaExample"

click the "Update" button

If everything went Ok, you should now be able to open the generated project and build/run the example.

OSX

Open the Xcode project, select the "luaExample Debug" scheme, and hit "Run".

Linux

Open the Code::Blocks .cbp and hit F9 to build. Optionally, you can build the example with the Makefile.

To build and run it on the terminal:

make
make run

How to Create a New ofxLua Project

ProjectGenerator

Simply select ofxLua from the available addons in the ProjectGenerator before generating a new project.

Manual Method

To develop your own project based on ofxLua, simply copy an example project and rename it. You probably want to put it in your apps folder, for example, after copying:

On Mac, rename the project in Xcode (do not rename the .xcodeproj file in Finder!): Long click on the project name in the project tree.

Adding ofxLua to an Existing Project

ProjectGenerator

Select ofxLua and other addons used by your project from the available addons in the ProjectGenerator, select the parent folder of your project, and set the exact name of the existing project in the text box. This will overwrite the existing project files with new ones that now include ofxLua.

Note: you will lose any custom settings you've added manually to your project.

Manual Method

If you want to add ofxLua to another project, you need to make sure you include the following src files:

Finally you need to include the header and library search paths required by luadbind. The provided static library xcode project includes the /usr/local/lib and /usr/local/lib search paths (as used by the Homebrew package manager) to the luabind static lib target. You'll need to change these if Boost is installed to a different dir.

OF API Bindings

SWIG generated bindings for the OF API can be found in src/bindings. Currently it covers most of the api while leaving out base classes. More specific documentation may come at a future date, but for now check the example scripts on usage.

Basic documentation:

There is a main "of" module and functions, classes, constants, & enums are renamed:

function: ofBackground -> of.background

class: ofColor -> of.Color

constant: OF_LOG_VERBOSE -> of.LOG_VERBOSE

enum: ofShader::POSITION_ATTRIBUTE -> of.Shader.POSITION_ATTRIBUTE

"begin" & ""end": these are lua keywords, so functions with this name are renamed in the following classes:

%module my
%{
// include any needed headers here
#include "MyCode.h"
%}
// include support for some common C++ STL types you might be using,
// see http://swig.org/Doc3.0/Library.html#Library_stl_cpp_library
%include <stl.i>
%include <std_string.i>
%include <std_vector.i>
%include <std_map.i>
// if you're using "string" instead of "std::string" (like the openFrameworks source code),
// you'll need this so swig will know that a "string" can be considered a "std::string"
typedef std::string string;
// include custom code you want to be wrapped,
// note the '%' instead of '#' as '%include' is a SWIG
// command to wrap code in the given header
%include "MyCode.h"

That's it, swig will handle the rest! Of course this is a simple example but there are lots more options for specific bindings settings such as generating properties from getters & setters, etc.

Generate .cpp Wrapper

Make sure to add search paths to headers used by your code (aka the "-I" line in the command above).

If all went well, SWIG will have generated the MyBindings_wrap.cxx C++ file. Put this into your project's source directory and build it with your project.

Opening Your Lua Library

You will need to open your new Lua library provided by the SWIG-generated .cpp file in order to use it in your lua state.

SWIG creates a "luaopen" C function using your module name which, in this case, will be "luaopen_my". This function needs to be defined in C++ in order to be used, so add it to the top of the .cpp file where you initialize your ofxLua object:

See the SWIG interface file in swig and the SWIG and Lua documentation for more information. SWIG will handle most genral cases for you, but there are plenty of details to get into if you want greater customization.

If you end up having lots of custom code to bind, it's recommended to create multiple SWIG interface files which are included into a single *.i using the %include command. Do not create seaprate files with the same module name, only set the module in the main file as SWIG is designed for 1 module per main interface.

Do not open issues or bug reports if the problem is in writing your own bindings as this is all handled by SWIG. Be sure to search online for similar errors with "swig" as part of your search. More likely than not, it's an issue with your bindings and not with ofxLua.

Lua require

Lua's require command will import scripts but doesn't know about the OF data path, so it will fail when using a relative path since the working directory for an OF app is the executable directory by default:

YourApp/bin/data/scriptA.lua
YourApp/bin/data/scriptB.lua

scriptA.lua:

require "scriptB"

require will fail since the current working directory is notYourApp/bin/data.

The easiest fix for this is to change the current working directory of the app to the directory of the script which is calling require. Setting the changeDir argument to true when calling ofxLua::doScript() will change the directory for you: