5

I have written a little program in C to manage a bibliography database in SQLite3. So far, this is only a command line tool that allows importing and exporting BibTeX data. To make the export/import functionality more customizable (e.g. always combine year&month fields in the date field on import, or skip certain fields on export) these functions are written in Lua and called from C. Now I want Lua to be an optional dependency. What's a good way to do that? I.e. if at compile time Lua is not found, fall back to more basic import/export functionality.

Right now, e.g. on export I get the data from SQL (sqlite3_exec) and write it directly to a Lua table in the callback function, like so (stripped stackoverflow-handling ;-) ):

int db_meta_cb(void *udata, int n, char **cval, char **ckey) {
  while (n-- > 0) {
    lua_pushstring(L, cval[n]);
    lua_setfield(L, -2, ckey[n]);
  };
};

Then there is a Lua function that takes such a table as an argument and pretty-prints a BibTeX entry. Similar story on import: the BibTeX parser (Lex/YACC generated C code) writes a Lua table and calls a 'cleanup' Lua function, then reads the result from the same Lua table and inserts it into the database.

Now this feels wrong in the sense that I use Lua too much, I guess because the data consists of (key,value)-pairs.

Note that one reason for this project is to experiment with/learn about embedding Lua in C, so please don't suggest (a) using one of the available Bibliography managers, or (b) rewriting everything in Python or Lua entirely... (Which I have already done btw)

1k5
  • 342
  • 6
  • 15
  • 5
    Why not including the Lua source code in your project and compile statically against it? At least, this would spare you the effort required for additional coding. – michaelmeyer Jul 08 '14 at 17:21
  • 4
    Indeed, one of the design principles of Lua is to be small and lightweight, so that you can link it to your program without bloating it. – Colonel Thirty Two Jul 08 '14 at 17:49
  • Since Lua is indeed small and also very portable, this is certainly worth considering. Thanks, I had not thought of this before. I guess in addition I don't like the 'style' I use now, where almost every function in some way accesses the Lua state, since its used to store data. – 1k5 Jul 08 '14 at 21:13

1 Answers1

1

The most elegant way I have seen this issue approached is via dynamic loading. Instead of linking your program against lua, at runtime, attempt to load the library manually using the dlopen family of functions.

If this then fails you can set a global flag that you will need to resort to the other method of providing the functionality but if it succeeds use the dlsym function to get the functions out of the lua shared object and use them. You can produce a very elegant solution in which you populate some function pointers with either the lua or legacy versions, then you can simply make the decisions once and call the functions not caring which implementation is in use.

Vality
  • 6,577
  • 3
  • 27
  • 48