Использование LuaLaTeX и SQLite3

Использование LuaLaTeX и SQLite3

Я пытаюсь получить доступ к базам данных SQLite из LuaLaTeX, но не могу загрузить установленный lsqlite3пакет. Вот что я пробовал до сих пор:

  1. Произвел совершенно новую установку Xubuntu 14.04
  2. Установлен полный TeX Live 2014
  3. Установлен Luarocks (который по пути установил Lua5.1)
  4. Использовал Luarocks для установкиlsqlite3

    uwe@luabuntu:/media/uwe$ список luarocks

    Установленные камни:

    lsqlite3 0.9.1-2 (установлен) - /usr/local/lib/luarocks/rocks

  5. Добавлен package.pathв следующий TeX-файл:

    \documentclass{article}    
    \usepackage{luacode}
    
    \begin{document}
    
    \begin{luacode*}
      package.path="/usr/local/lib/luarocks/rocks;/usr/local/lib/luarocks/rocks/lsqlite3; 
      /usr/local/lib/lua/5.1/lsqlite3.so" .. package.path
    
      require("lsqlite3")
    \end{luacode*}
    
    Hello Lua!
    
    \end{document}
    

Я получаю следующую ошибку:

! LuaTeX error [\directlua]:3: module 'lsqlite3' not found:
  no field package.preload['lsqlite3']
  [luatexbase.loader] Search failed
  [kpse lua searcher] file not found: 'lsqlite3'
  [kpse C searcher] file not found: 'lsqlite3'
  [oberdiek.luatex.kpse_module_loader]-eroux Search failed
stack traceback:
  [C]: in function 'require'
  [\directlua]:3: in main chunk.
\luacode@dbg@exec ...code@maybe@printdbg {#1} #1 }

l.9 \end{luacode*}

Что необходимо настроить, чтобы LuaLaTeX нашел lsqlite3пакет?

РЕДАКТИРОВАТЬ

Я постарался все отрегулировать, следуя комментариям ниже:

  1. Скорректировано/usr/local/texlive/2014/texmf.cnf
  2. Поместите все в пример
  3. Все еще получаю ошибку об отсутствующем lsqlite3модуле в следующем примере

    \documentclass{article}
    \directlua{
    require "lualoader"
    }
    
    \usepackage{fontspec}
    \usepackage[english]{babel}
    \begin{document}
    
    \directlua{package.path='/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua;/home/uwe/.luarocks/share/lua/5.1/?.lua;/home/uwe/.luarocks/share/lua/5.1/?/init.lua;/usr/share/lua/5.1//?.lua;/usr/share/lua/5.1//?/init.lua;./?.lua;/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua;/usr/local/lib/lua/5.1/?.lua;/usr/local/lib/lua/5.1/?/init.lua;/usr/share/lua/5.1/?.lua;/usr/share/lua/5.1/?/init.lua'
    package.cpath='/usr/local/lib/lua/5.1/?.so;/home/uwe/.luarocks/lib/lua/5.1/?.so;./?.so;/usr/local/lib/lua/5.1/?.so;/usr/lib/x86_64-linux-gnu/lua/5.1/?.so;/usr/lib/lua/5.1/?.so;/usr/local/lib/lua/5.1/loadall.so'
    require "lualoader"
    }
    
    \directlua{%
    local sqlite3 = require("lsqlite3")
    local db = sqlite3.open_memory()
    
    db:exec[[
      CREATE TABLE test (id INTEGER PRIMARY KEY, content);
    
      INSERT INTO test VALUES (NULL, 'Hello World');
      INSERT INTO test VALUES (NULL, 'Hello Lua');
      INSERT INTO test VALUES (NULL, 'Hello Sqlite3')
    ]]
    
    for row in db:nrows("SELECT * FROM test") do
      tex.print(row.id .. " : ".. row.content )
    end
    
    }
    \end{document}
    

решение1

Можно изменить механизм загрузки пакетов в Lua. В случае LuaTeXбиблиотека kpseиспользуется для загрузки модулей вместо механизма по умолчанию, который использует package.pathи package.cpath. Поэтому установка этих переменных не даст никакого эффекта. Но ничто не мешает нам использовать оба метода с помощью Luaмодуля lualoader.lua. Сохраните фрагмент ниже как файл в каталоге, содержащем ваш документ:

-- lualoader.lua
-- this is copied from luatexbase.loader
local make_loader = function(path, pos, loadfunc)
  local default_loader = package.searchers[pos]
  local loader = function(name)
    local file, _ = package.searchpath(name,path)
    if not file then
      local msg = "\n\t[lualoader] Search failed"
      local ret = default_loader(name)
      if type(ret) == "string" then
        return msg ..ret
      elseif type(ret) == "nil" then
        return msg
      else
        return ret
      end
    end
    local loader,err = loadfunc(file, name)
    if not loader then
      return "\n\t[lualoader] Loading error:\n\t"..err
    end
    return loader
  end
  package.searchers[pos] = loader
end

local binary_loader = function(file, name)
  local symbol = name:gsub("%.","_")
  return package.loadlib(file, "luaopen_"..symbol)
end

make_loader(package.path,2,loadfile)
make_loader(package.cpath,3, binary_loader)

Мы используем функцию make_loaderдля вставки функции поиска package.pathили package.cpathпо указанному индексу в package.searchersтаблице. 2для lua-файлов, 3для бинарных модулей. Нам также нужно использовать разные функции для загрузки модуля в зависимости от его типа. Мы используем loadfileдля Luaфайлов и немного более сложную функцию для бинарных модулей, которая использует package.loadlib.

В качестве примера можно попробовать выполнить загрузку lsqlite3из LuaTeX:

\documentclass{article}
\directlua{
require "lualoader"
}

\usepackage{fontspec}
\usepackage[english]{babel}
\begin{document}
\directlua{%
local sqlite3 = require("lsqlite3")

local db = sqlite3.open_memory()

db:exec[[
  CREATE TABLE test (id INTEGER PRIMARY KEY, content);

  INSERT INTO test VALUES (NULL, 'Hello World');
  INSERT INTO test VALUES (NULL, 'Hello Lua');
  INSERT INTO test VALUES (NULL, 'Hello Sqlite3')
]]

for row in db:nrows("SELECT * FROM test") do
  tex.print(row.id .. " : ".. row.content )
end

}
\end{document}

Важно запускать LuaLaTeX с --shell-escapeфлагом, так как бинарные библиотеки по умолчанию заблокированы. С помощью --shell-escapeможно запускать внешние программы и вызывать бинарные библиотеки.

Пример дает:

введите описание изображения здесь

Редактировать:

КакУвеуказано, luarocksчто при установке некоторыми менеджерами пакетов Linux может работать некорректно. Я столкнулся с этим в Fedora, поэтому я установил luarocksиз исходников. Другим решением может быть установка package.pathи package.cpathв каталоги, перечисленные командой

luarocks path

В моей системе это дает:

$ luarocks path
export LUA_PATH='/home/michal/.luarocks/share/lua/5.2/?.lua;/home/michal/.luarocks/share/lua/5.2/?/init.lua;/usr/local/share/lua/5.2/?.lua;/usr/local/share/lua/5.2/?/init.lua;/usr/share/lua/5.2/?.lua;/usr/share/lua/5.2/?/init.lua;/usr/lib/lua/5.2/?.lua;/usr/lib/lua/5.2/?/init.lua;./?.lua'
export LUA_CPATH='/home/michal/.luarocks/lib/lua/5.2/?.so;/usr/local/lib/lua/5.2/?.so;/usr/lib/lua/5.2/?.so;/usr/lib/lua/5.2/loadall.so;./?.so'

Таким образом, измененная преамбула будет выглядеть так:

\directlua{    
package.cpath = '/home/michal/.luarocks/lib/lua/5.2/?.so;/usr/local/lib/lua/5.2/?.so;/usr/lib/lua/5.2/?.so;/usr/lib/lua/5.2/loadall.so;./?.so'
package.path = '/home/michal/.luarocks/share/lua/5.2/?.lua;/home/michal/.luarocks/share/lua/5.2/?/init.lua;/usr/local/share/lua/5.2/?.lua;/usr/local/share/lua/5.2/?/init.lua;/usr/share/lua/5.2/?.lua;/usr/share/lua/5.2/?/init.lua;/usr/lib/lua/5.2/?.lua;/usr/lib/lua/5.2/?/init.lua;./?.lua'
require "lualoader"
}

решение2

По состоянию на май 2017 года на CTAN есть пакет под названиемluapackageloader, который позволяет изменить поведение поиска пакетов по умолчанию в LuaTeX.

После загрузки luapackageloader, выполнение requireсначала попробует поисковик по умолчанию на основе kpse. Если модуль не найден, он также попытается загрузить пакет из значений Lua package.pathи .package.cpath

Пример использования

\documentclass{article}    
\usepackage{luacode}
\usepackage{luapackageloader}

\begin{document}

\begin{luacode*}
  package.path="/usr/local/lib/luarocks/rocks;/usr/local/lib/luarocks/rocks/lsqlite3; 
  /usr/local/lib/lua/5.1/lsqlite3.so" .. package.path

  require("lsqlite3")
\end{luacode*}

Hello Lua!

\end{document}

Дополнительное примечание: вы можете сделать eval $(luarocks path)в своей оболочке, чтобы задать путь к пакету, используя переменные окружения, которые интерпретатор Lua подхватит автоматически. Таким образом, вам не нужно возиться с собой package.path.

решение3

На основе комментариевэтот вопрос, у меня есть следующая строка /usr/local/texlive/2014/texmf.cnf:

CLUAINPUTS  = .;$SELFAUTOLOC/lib/{$progname,$engine,}/lua//;/usr/lib/{$progname,$engine,}/lua//

Но мой luarocks listдает:

Installed rocks:

lsqlite3
   0.9.1-2 (installed) - /usr/lib/luarocks/rocks-5.2

поэтому вам может потребоваться настроить второй путь в соответствии с вашей установкой.

решение4

Краткое содержание

Поиск пакета

  • В обычном Lua пакет ищется в package.pathи package.cpath.

  • В LuaTeX поиск пакетов по умолчанию выполняется с помощью kpse.

  • Есть 2 способа изменить место, где LuaTeX ищет пакеты.

  1. изменить поведение kpse

    Измените texmf.cnfфайл, переменные LUAINPUTSи CLUAINPUTS.

  2. заставить Lua загрузиться из package.(c)path, затем изменить их

    • При использовании \usepackage{luapackageloader}пакеты ищутся как в kpse, так и в package.(c)path.

    • Значение package.(c)pathможет быть установлено пользователем вручную в самом коде Lua, нолучше установить переменные окружениянапример LUA_PATH, LUA_CPATH.

      Если вы работаете eval $(luarocks path)в bash, все процессы, порожденные этой оболочкой bash, унаследуют переменные среды.

Двоичный пакет

  • Если пакет требуетдвоичные файлы, --shell-escapeнеобходимо пройти.

Версионирование

  • Версия пакетадолжен быть совместим с версией Lua. Сделайте это print(_VERSION)в Lua для проверки.

    Чтобы указать конкретную версию luarocks, выполните, например luarocks --lua-version 5.3 path, .

Связанный контент