Написание модуля lua C для Lua 5.X

#c #lua

#c #lua

Вопрос:

Я пытаюсь написать модуль Lua, который работает с Lua 5.0.x-5.4.x. Поскольку каждая второстепенная версия, похоже, вносит и плохо документирует изменения в C API, которые нарушают обратную совместимость, я хотел бы знать, как я могу добиться этого с наименьшим количеством условной компиляции на основе Luaверсия.

Например, вот что должно работать для Lua 5.1, но не для более поздних версий:

 #define LUA_LIB
#include "lua.h"
#include "lauxlib.h"

static int foo(lua_State *L)
{
  int a = luaL_checknumber(L, 1);
  int b = luaL_checknumber(L, 2);

  lua_pushnumber(L, a   b);

  return 1;    
}

luaL_Reg foolib[] = {
  {"foo", foo},
  {NULL, NULL}
};

LUALIB_API int luaopen_foo(lua_State *L)
{
  luaL_register(L, foolib);
  return 1;
}
 

Как я могу адаптировать это для работы с Lua5.2 и далее? И, может быть, даже сделать его устойчивым к будущим изменениям API?

Комментарии:

1. Просмотрел Lua изменения с 5.1 to 5.4 (сегодняшняя версия), имо, вам лучше использовать разные файлы для каждой версии. Если бы я заботился о поддержке всех Lua версий, я бы так и сделал.

2. Можете ли вы привести пример плохо документированной несовместимости, которую вы когда-либо находили? Все несовместимости, с которыми я когда-либо сталкивался при обновлении Lua, были очень хорошо документированы.

3. Взгляните на Compat-5.3 здесь , в котором для вас уже настроена большая часть элементов условной компиляции (по крайней мере, до Lua 5.3). В будущем может появиться версия Lua 5.4 (для этого есть открытая проблема), но между 5.3 и 5.4 не так много изменений в C API (которые можно исправить с помощью условной компиляции). Кроме того, LUA_LIB LUALIB_API макросы и предназначены для вспомогательных функций Lua API, а не для 3rdмодули расширения для сторонних разработчиков.

Ответ №1:

Следующий фрагмент кода должен помочь вам начать:

 #include <lua.h>
#include <lauxlib.h>
#include "compat-5.3.h"


static int foo(lua_State* L)
{
  lua_Integer a = luaL_checkinteger(L, 1);
  lua_Integer b = luaL_checkinteger(L, 2);
  lua_pushinteger(L, a   b);
  return 1;
}


static luaL_Reg const foolib[] = {
  { "foo", foo },
  { 0, 0 }
};


#ifndef FOO_API
#define FOO_API
#endif

FOO_API int luaopen_foo(lua_State* L)
{
  luaL_newlib(L, foolib);
  return 1;
}
 

Он опирается на порт C-API проекта Compat-5.3, компилируется и запускается на Lua 5.1 — 5.4. Compat-5.3 обеспечивает совместимость с Lua 5.3 для Lua 5.1 и 5.2. Все, что вам нужно, это заголовок и исходный файл C. Для модулей с одним исходным файлом вы можете просто включить заголовок, для модулей с несколькими исходными файлами вы должны дополнительно определить символ препроцессора и скомпилировать / связать compat-5.3.c файл отдельно. См. README.md за подробностями. Планируется запустить проект Compat-5.4 (см. Этот выпуск ), но API Lua 5.4 C в любом случае в основном совместим с Lua 5.3.

К сожалению, для поддержки Lua 5.0 вы сами по себе.

Комментарии:

1. Это очень удобно. Я все еще думаю, что, к сожалению, необходимость в подобном решении даже существует, но, по крайней мере, оно работает.

Ответ №2:

Ваш код работает без изменений в Lua 5.2 , если вы измените

 luaL_register(L, foolib);
 

Для

 luaL_newlib(L, foolib);
 

Если вам нужно обслуживать Lua 5.0 и Lua 5.1, вам понадобится заголовок compat. Я рекомендую вам написать код для последней версии Lua и написать макросы совместимости для предыдущих версий. Смотрите Мои библиотеки для примеров.