Lua Interface C

In the second kind, Lua has the control and C is the library. Here, the C code is called library code. Both application code and library code use the same API to communicate with Lua, the so called C API. The C API is the set of functions that allow C code to interact with Lua. It comprises functions to read and write Lua global variables, to. This section describes the C API for Lua, that is, the set of C functions available to the host program to communicate with Lua. All API functions and related types and constants are declared in the header file lua.h. Even when we use the term 'function', any facility in the API may be provided as a macro instead. This is an interesting tip. It shows the recipe for writing a DLL in native C/C can be called from Lua. Warning you'll need to be comfortable with low level C/C for this to be of use to you. The good thing is the C is the linga-franca for computer operating systems - once you can get to C you can get to.

Lua, Sol 3 and C++ (Oh, My!) : Part 1 - Nice Doggy.

To start with the easiest, create a console project so that you can see the print outs from Lua. Lua problems with C. Lua is written in C, the whole Lua API is C based. Hence converting Lua into the C world would seem rather difficult, but Lua does provide abilities to do this. Lua Interface is a library for integration between the Lua language and Microsoft.NET's Common Language Runtime (CLR). Lua scripts can use this to instantiate CLR objects, access properties, call methods, and even handle events with Lua functions.

I've seen a couple of questions now about embedding Lua in C++. While it is certainly possible to use the C API in C++, I wanted to introduce a pure C++ interface to Lua called Sol 3. Sol3 is a template based approach to Lua. It is extremely fast and has some very slick features for interfacing with Lua that almost completely eliminates the need to access the Lua stack.
Now, lets be very clear: I suck at C++. I think it's an abysmal language and it's practitioners are masochists. Every time I try and interface C++ with Lua I am struck by the complete dissimilarities. One is a large, complex monster ready to eat your children and destroy months of your life; the other a wonderful tool for usefully automating the world. If you read this 'article' (rant?) let the curse that is C++ be on your head, I wash my hands. Now for the foolhardy, let us have a look.
Sol 3 works with G++ (GNU C++ compiler) and Microsoft Visual C++ (e.g. Visual Studio 'proper'), but I will be using my WinLua Toolchain (LLVM/CLang) on Windows 10 with VS Code (not Visual Studio 'proper'). WinLua Toolchain is installed via MSI and consists of Lua 5.3, Lua Rocks (package manager), a compiler and the most sublime build system: xmake. While I am eager to announce WinLua, it's still not quite ready. Feel free to download and follow along, but the debugger doesn't work in VS Code (GDB command line only!) and LuaRocks is a little finky. The MSI uninstaller completely removes it from your system, so using it is relatively risk free. None the less, there should be a full WinLua release before the end of the year.
While build systems are plentiful, I will rely on xmake for this article. If you wish to use xmake without Winlua (e.g. with VC++ or Mingw-64), download instructions are here.
Sol 3
Sol 3 is a 'Header Only' Lua interface (5.1+) to C++ written against the C++ 17 standard. Header Only, means you don't have to build a library, or add source trees. C++17 is important because it takes advantage of all the latest tools and compiler tricks to make your Lua calls lightening fast. To use Sol 3 you just include the header in your C++ application and you're done. That simple! There are some parts that are pure magic and completely obfuscate the boundaries between C++ and Lua. However, Sol3 is, a tricky beast due to it being C++17 and primarily written in C++ templates and there are decisions and design tradeoffs that will need to be made later in your projects. Most of that difficulty, however, is outside the scope of this article.
The documentation for Sol 3 is quite extensive and the tutorials/examples are plentiful. Getting started is relatively easy. However, even after spending time with the tutorials, I often found myself asking 'ya, but I just want to...', 'sure, but what if I need to...' and so forth. That was true until I started to understand the brilliant use of generics to make accessing Lua very simple. Unfortunately the API reference is dense C++ templates written for those who are already initiated. Remember, this is C++ and you are supposed to know what you're doing. None the less, I hope to spell out some of those rough spots.
Finally, a note about where to find help. While I can provide some information, I am only a few steps ahead of you in my use of Sol 3 (remember, I don't like C++). The Sol 3 maintainer/author is amazing and should be your go-to source for issues. The Phantom Derpstorm - aka ThePHD - has always answered my github questions very quickly and provided the necessary - albeit densely technical - solutions. And no, ThePHD is not a doctor (yet

Lua Cpp Interface

? I embarrassed myself on the lua-l mailing list once).
So, without further ado, lets get started.
- Lua 5.3+
- C++ Compiler and build tools
- Sol header file
- IDE, preferably a debugger
- (optional) Command line shell (powershell, terminal, WSL, gitbash, msys2, etc.)
InterfaceIf you already have Lua and a compiler toolchain set up, then download the Sol 3 git repository and copy the 'single' hpp file to your include directory:
(Note the repository is still called sol2. Officially Sol 3 is called Sol 2 v3. <head explodes>)

If you've decided you want to follow along with WinLua, then download WinLua Toolchain, and run the installer. Sol 3 comes packaged with Winlua so it is already installed.
WinLua Setup in VS Code
Next, download and open Visual Studio Code and install two add ins: xmake and C++.
First, C++...
Next, the xmake plugin
If you clear your search box, you will see the two installed plugins:
You can now set up a folder for your project. Once you've created your containing folder (in my case, thats LuaSolExample), I need to create some subfolders and an empty file for Sol. We need to create includesolconfig.hpp by right clicking, creating the include folder, then double click into the include folder, then creating the sol folder. Finally, in the sole folder, right click and create a 'new text file' and rename the file config.hpp. *NOTE: If you have file extensions hidden in Windows Explorer, you will need to show extensions (menu bar -> view -> check File name extentions) and remove the '.txt' at the end.* Create a folder, then right click in the folder and select 'open in VSCode'.
With this part complete, there are only one or two more 'WinLua specific steps for VS Code', but for now, lets move on to some generic code.
Hello World
In you editor of choice, create a file called main.cpp and enter the following contents:

This code is almost directly from the Sol 3 tutorials. As you can see, getting started is amazingly simple. With three lines of code, we can get Lua to say something for us.
As with any C or C++ program, there are two things that need to be specified in order to complete our application:
1) We need to tell a compiler where to find the header files included in our project and
2) We need to tell the linker where to find the binaries that contain the functionality that we want to include in our application.
In our case, we need the compiler to know where the sol.hpp file and the config.hpp files are located, as well as the header files for Lua. While you can see that we have not included any Lua headers in our application, the Sol 3 library links to Lua for us, so we need to specify them too.
As for the binary libraries that actually contain the functionality, we are lucky in that only a Lua library is required because Sol 3 is a header only implementation. Note that if you are using WinLua or Microsoft VC++ (`cl`), you will need to have a *.lib file for Lua. That file can be a static lib or a linking lib, but you need that file. A lua53.dll file will not work by itself. If you are using GNU g++, you are exempt (`ld` will link directly to a DLL. yikes!).
Now, if you are using Visual Studio VC++, you will need to drill into endless dialog boxes and specify the correct settings. I will not specify the VS configuration here, but if someone asks in the comments, I will perhaps relent.
Building Our Example
While one could use Visual Studio (msbuild from the command line), WinLua provides three possible build systems: the veritable GNU `make` ('gmake'), the sublime lua based `xmake`, and `luarocks`. GNU `make` is excellent if you have a long grey unix beard or you are particularly keen on slamming your head against hard objects. Luarocks is excellent if you are creating Lua modules only. Since neither of these scenarios applies directly to this article, we will skip to xmake (And in case my bias wasn't obvious enough - because it's my favorite and I am the one writing this article, so there).
Open powershell and `cd` into your directory. I use Windows Terminal from the Windows store:

Xmake is excellent at detecting existing toolchains. If VC++ is installed, it will find that first.

If GNU mingw-64 is available in the path, it will find that (if VC++ isn't present). For our example, I am going to set a global mingw directory and specify the project configuration parameters:

The following table explains the switches:
Specified 'config' to configure the project​
Architecuture - i386 or i686 can be specified for 32 Bit. x86_64 is the 64 bit designation.
WinLua is only 32 bit at the moment so we will use i686. WinLua 64 bit is not far off.​
Platform: Mingw is the C/C++ library we will be using.​
Compilation 'mode'. Also known as a build configuraiton.​

xmake will also generate a new xmake.lua file for you. If we try it however, it will fail because we haven't specified our headers or link libraries:

Let's pop open VS Code again and update our xmake.lua file

Our xmake file specifies a 'target', being the thing we are going to build. Within that target it sets the kind of build and adds our C++ file. However, what it does not do yet is define where our header files are, or where our link libraries are. Lets add that now:

We have added three lines that tell the compiler and linker where to find the pieces they need to complete the program. I have used the include directory for WinLua because Sol and all the Lua files are in there. I have also added our own include directory so that the system can find sol/config.hpp. If you put Sol 3 in your own include directory, your includes would like something like this:

Now lets try again from the command line:

Ooops. That didn't go well. What happened? I left this error in here because it's an important one to know about. This error is telling you in a round about way that you are using the wrong C++ standard. Remember, Sol 3 uses C++17. Most compilers default to C++11 or C++14. Let's fix that using a compiler option in our xmake.lua file:

Save the file, drop back to the command line, and lets try again. (Note that `xmake`, `xmake build` and `xmake b` all run the build command):

OH MY GOD! It worked, it worked, it worked it...(dance of joy). Ahem. I mean: As you can see, we have now compiled our first Lua/C++ application. Let's try running it:
In this article I have very, very, very briefly outlined how to link Lua to C++ using the Sol 3 Lua bindings. If you want to charge ahead, there are plenty of samples in the Sol 3 documentation and in the repository. Next week(ish), I will post the second part of the article outlining a simple use of Sol 3. If you are familiar with Lua's stack based access, the simplicity of Sol 3 will blow your mind. If you've not had the 'pleasure' of accessing Lua from C, then Sol 3 is going to spoil you. Either way, I think you'll appreciate the masterpiece that will shed light on Lua/C++ (Sol means sun in portugese. 'shed light', sun... get it?)

This is the Technical Reference. Please see UCI (Unified Configuration Interface) – Usage

Source code is available here

What is UCI?

UCI is a small utility written in C (a shell script-wrapper is available as well) and is intended to centralize the whole configuration of a device running OpenWrt. UCI is the successor of the NVRAM based configuration found in the historical OpenWrt branch White Russian and a wrapper for the standard configuration files programs bring with them, like e.g. /etc/network/interfaces, /etc/exports, /etc/dnsmasq.conf, /etc/samba/samba.conf etc.

UCI configuration files are located in the directory /etc/config/
Their documentation can be accessed online in the OpenWrt-Wiki under UCI configuration files.

They can be altered with any text editor or with the command line utility program uci or through various programming APIs (like Shell, Lua and C). The WUI luci e.g. uses Lua to manipulate them.

Dependencies of UCI

    • libuci-lua is a libuci-plugin for Lua which is utilized by e.g. luci

Both are maintained in the same git as UCI.


The functionality is provided by the two packages uci and libuci. The package libuci-lua is also available.

Name Size in Bytes Description
uci 7196 Utility for the Unified Configuration Interface (UCI)
libuci 18765 C library for the Unified Configuration Interface (UCI)
libuci-lua ~6000 libuci-plugin for Lua, e.g. luci makes use of it

Installed Files


path/file file type Description
/sbin/uci binary uci executable
/lib/config/ shell script Shell script compatibility wrappers for /sbin/uci


path/file file type Description
/lib/ symlink symlink to
/lib/ binary Library


path/file file type Description
/usr/lib/lua/ binary Library

Lua Bindings for UCI

For those who like lua, UCI can be accessed in your code via the package libuci-lua. Just install the package then, in your lua code do


top level entry point

uci.cursor() instantiates a uci context instance, e.g:

if you want to involve state vars:

if you need to work on UCI config files that are located in a non standard directory:

on that you can call the usual operations

Get value (returns string or nil if not found):

Set simple string value:

Set list value:

Delete option:

Delete section:

Add new anonymous section “type” and return its name:

Add new section “name” with type “type”:

Iterate over all section of type “type” and invoke a callback function:

In the preceding example, s is a table containing all options and two special properties:

  • s['.name'] → section name

If the callback function returns false [NB: notnil!], foreach() will terminate at that point without iterating over any remaining sections.foreach() returns true if at least one section exists and the callback function didn't raise an error for it; false otherwise.

Here's another example:

Move a section to another position. Position starts at 0. This is for example handy to change the wireless config order (changing priority).

Discard any changes made to the configuration, that have not yet been committed:

commits (saves) the changed configuration to the corresponding file in /etc/config

That's basically all you need.

About uci structure

It took me some time to understand the difference between “section” and “type”. Let's start with an example:

Here, x:get(“system”,“@rdate[0]”,“server”) won't work. rdate is a type, not a section.

Here is the return of x:get_all(“system”):

[“.type”] gives the type of the section;

Vlc Lua Interface Configuration

[“.name”] gives the real name of the section (note that these names are auto-generated);

[“.index”] is the index of the list (starting from 1);

From what I know, there seem to be no way to access “@rdate[0]” directly. You have to iterate with x:foreach to list all the elements of a given type.

I use the following function:

getConfType(“system”,“rdate”) returns:

So if you want to modify [email protected][0].server you need to iterate the type, retrieve the section name [“.name”] and then call:

Hope this helps.


(Luci has however a Cursor:get_first function that is similar to get except it takes a type instead as section as second argument.)

Additional Information

See also LuCI UCI model functions. That's what LuCI uses. It extends the uci cursor class with a few more convenience functions.

Usage outside of OpenWrt

If you want to use the libuci apart from OpenWrt (for e.g. you are developing an application in C on your host computer) then prepare as follows:Note that libuci depends on [libubox]

Grab the source.

Go to the source directory (where the CMakeLists.txt lives) and optionally configure the build without Lua bindings:

Build and install uci as root (this will install uci into /usr/local/, see this thread on how to install and use uci without root permissions in your home directory:

Setup library search paths using

Setting your system library search path can be done in many ways, and is largely out of scope of the OpenWrt wiki.

Open /etc/ and add the place where you installed the uci library:

Add this line somewhere to /etc/

Execute ldconfig as root to apply the changes to /etc/

Setup library search paths using Using LD_LIBRARY_PATH

Alternatively, just

Building your own application

Luci - Lua Configuration Interface

To compile your application you have to link it against the uci library. Append -luci in your Makefile:

And examples on how to use UCI in C can be found in this thread: get more examples look into the source directory of uci which you got by git clone and open cli.c or ucimap-example.c


Luainterface Github

All uci set, uci add, uci rename and uci delete commands are staged in /tmp and written to flash at once with uci commit.This obviously does not apply to people using text editors, but to scripts, guis and other programs working with uci files.

Lua C Interface Example

This website uses cookies. By using the website, you agree with storing cookies on your computer. Also you acknowledge that you have read and understand our Privacy Policy. If you do not agree leave the website.More information about cookies