Verwenden von LuaLaTeX und SQLite3

Verwenden von LuaLaTeX und SQLite3

Ich versuche, von LuaLaTeX aus auf SQLite-Datenbanken zuzugreifen, kann aber ein installiertes lsqlite3Paket nicht laden. Folgendes habe ich bisher versucht:

  1. Habe eine brandneue Xubuntu 14.04 Installation durchgeführt
  2. Installiert ein komplettes TeX Live 2014
  3. Luarocks installiert (wobei Lua5.1 nebenbei installiert wurde)
  4. Verwendet Luarocks zu installierenlsqlite3

    uwe@luabuntu:/media/uwe$ Luarocks-Liste

    Installierte Steine:

    lsqlite3 0.9.1-2 (installiert) – /usr/local/lib/luarocks/rocks

  5. Angehängt package.pathan die folgende TeX-Datei:

    \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}
    

Ich erhalte die folgende Fehlermeldung:

! 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*}

Was muss eingestellt werden, damit LuaLaTeX das lsqlite3Paket findet?

BEARBEITEN

Ich habe versucht, alles gemäß den folgenden Kommentaren anzupassen:

  1. Angepasst/usr/local/texlive/2014/texmf.cnf
  2. Setzen Sie alles in das Beispiel ein
  3. lsqlite3Bei folgendem Beispiel erhalte ich immer noch die Fehlermeldung über das fehlende Modul

    \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}
    

Antwort1

Es ist möglich, den Mechanismus zum Laden von Paketen in zu ändern Lua. Im Fall von wird LuaTeXdie kpseBibliothek zum Laden von Modulen verwendet, statt des Standardmechanismus, der package.pathund verwendet package.cpath. Das Setzen dieser Variablen hat also keine Auswirkungen. Aber nichts hindert uns daran, beide Methoden mit einem LuaModul zu verwenden, lualoader.lua. Speichern Sie den folgenden Codeausschnitt als Datei im Verzeichnis, das Ihr Dokument enthält:

-- 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)

Wir verwenden die Funktion, make_loaderum eine Suchfunktion package.pathoder eine Funktion package.cpathan einem bestimmten Index in der package.searchersTabelle einzufügen. 2Für Lua-Dateien, 3für Binärmodule. Wir müssen auch je nach Typ unterschiedliche Funktionen verwenden, um ein Modul zu laden. Wir verwenden loadfilefür LuaDateien eine etwas kompliziertere Funktion für Binärmodule, die verwendet package.loadlib.

Als Beispiel können wir versuchen, lsqlite3von folgendem Standort zu laden 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}

Es ist wichtig, LuaLaTeX mit diesem Flag auszuführen --shell-escape, da Binärbibliotheken standardmäßig blockiert sind. Mit --shell-escapekönnen Sie externe Programme ausführen und Binärbibliotheken aufrufen.

Das Beispiel ergibt:

Bildbeschreibung hier eingeben

Bearbeiten:

AlsUwedarauf hingewiesen, luarocksdass die Installation durch einige Linux-Paketmanager möglicherweise nicht richtig funktioniert. Ich habe dies unter Fedora erlebt, also habe ich es luarocksaus der Quelle installiert. Eine andere Lösung könnte darin bestehen, die durch den Befehl aufgelisteten Verzeichnisse package.pathund festzulegen.package.cpath

luarocks path

Auf meinem eigenen System ergibt dies:

$ 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'

Eine modifizierte Präambel wäre also:

\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"
}

Antwort2

Seit Mai 2017 gibt es auf CTAN ein Paket namensluapaketlader, mit dem Sie das Standardsuchverhalten für Pakete in LuaTeX ändern können.

Sobald Sie geladen haben luapackageloader, requirewird bei der Ausführung von zuerst der standardmäßige kpse-basierte Sucher ausprobiert. Wenn das Modul nicht gefunden wird, wird auch versucht, das Paket aus Luas package.pathund package.cpathWerten zu laden.

Anwendungsbeispiel

\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}

Zusätzliche Anmerkung: Sie können eval $(luarocks path)den Paketpfad in Ihrer Shell mithilfe von Umgebungsvariablen festlegen, die der Lua-Interpreter automatisch erkennt. Auf diese Weise müssen Sie nicht package.pathselbst daran herumfummeln.

Antwort3

Basierend auf Kommentaren zudiese Frage, ich habe die folgende Zeile in /usr/local/texlive/2014/texmf.cnf:

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

Aber mein luarocks listgibt:

Installed rocks:

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

Daher müssen Sie den zweiten Pfad möglicherweise entsprechend Ihrer Installation anpassen.

Antwort4

Zusammenfassung

Suche nach dem Paket

  • Im normalen Lua wird ein Paket in package.pathund gesucht package.cpath.

  • In LuaTeX wird ein Paket standardmäßig mit kpse gesucht.

  • Es gibt zwei Möglichkeiten, zu ändern, wo LuaTeX nach Paketen sucht

  1. Verhalten von kpse ändern

    texmf.cnfDatei, Variablen LUAINPUTSusw. ändern CLUAINPUTS.

  2. Lassen Sie Lua von laden package.(c)pathund ändern Sie dann diese

    • Mit \usepackage{luapackageloader}werden Pakete sowohl in kpse als auch in gesucht package.(c)path.

    • Der Wert package.(c)pathkann vom Benutzer manuell im Lua-Code selbst festgelegt werden.Es ist besser, Umgebungsvariablen festzulegenz.B LUA_PATH, LUA_CPATH.

      Wenn Sie eval $(luarocks path)in Bash ausführen, erben alle von dieser Bash-Shell gestarteten Prozesse die Umgebungsvariablen.

Binärpaket

  • Wenn das Paket erfordertBinärdateien, --shell-escapemuss bestanden werden.

Versionierung

  • Die Paketversionmuss mit der Lua-Version kompatibel sein. Führen Sie print(_VERSION)die Überprüfung in Lua durch.

    Um für Luarocks eine bestimmte Version anzugeben, geben Sie beispielsweise ein luarocks --lua-version 5.3 path:

verwandte Informationen