LuaLaTeXとSQLite3の使用

LuaLaTeXとSQLite3の使用

LuaLaTeX から SQLite データベースにアクセスしようとしていますが、インストールされたパッケージをロードできません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.pathpackage.cpathLualualoader.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または挿入します。lua ファイルの場合は 、バイナリ モジュールの場合は です。また、モジュールの種類に応じて、異なる関数を使用してモジュールをロードする必要があります。ファイルの場合は を使用し、バイナリ モジュールの場合は を使用する少し複雑な関数を使用します。package.cpathpackage.searchers23loadfileLuapackage.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}

--shell-escapeバイナリ ライブラリはデフォルトでブロックされるため、フラグ付きで LuaLaTeX を実行することが重要です。--shell-escapeこれにより、外部プログラムを実行し、バイナリ ライブラリを呼び出すことができます。

この例の結果は次のようになります。

ここに画像の説明を入力してください

編集:

としてウーヴェ指摘されているように、luarocks一部のLinuxパッケージマネージャによってインストールされたものは正しく動作しない可能性があります。私はFedoraでこれを経験したので、ソースからインストールしました。別の解決策としては、コマンドでリストされたディレクトリをluarocks設定することです。package.pathpackage.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年5月現在、CTANには次のようなパッケージがあります。luaパッケージローダーを使用すると、LuaTeX でのデフォルトのパッケージ検索動作を変更できます。

をロードしたらluapackageloader、 を実行すると、まずデフォルトの kpse ベースのサーチャーが試されます。モジュールが見つからない場合は、Lua のおよび値requireからパッケージのロードも試みます。package.pathpackage.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

そのため、インストールに応じて 2 番目のパスを調整する必要がある場合があります。

答え4

まとめ

パッケージの検索

  • 通常の Lua では、パッケージは および で検索されpackage.pathますpackage.cpath

  • LuaTeX では、パッケージはデフォルトで kpse で検索されます。

  • LuaTeXがパッケージを検索する場所を変更するには2つの方法があります

  1. kpseの動作を変更する

    texmf.cnfファイル、変数LUAINPUTSなどを変更しますCLUAINPUTS

  2. Luaを からロードしpackage.(c)path、それらを変更する

    • を使用すると\usepackage{luapackageloader}、パッケージは kpse と の両方で検索されますpackage.(c)path

    • の値はpackage.(c)pathLuaコード内でユーザーが手動で設定できますが、環境変数を設定する方が良い例えばLUA_PATHLUA_CPATH

      bash で実行するとeval $(luarocks path)、その bash シェルから生成されたすべてのプロセスが環境変数を継承します。

バイナリパッケージ

  • パッケージにバイナリファイル--shell-escape合格する必要があります。

バージョン管理

  • パッケージ版Luaバージョンと互換性がある必要がありますprint(_VERSION)確認するには Lua 内で実行します。

    luarocks に特定のバージョンを指定するには、次のようにしますluarocks --lua-version 5.3 path

関連情報