LaTeX備忘——通過lua調用C動態鏈接庫

    在上一篇日誌中記錄瞭如何在LaTeX文件中編寫、調用Lua腳本語言,本文進一步介紹如何在LaTeX中通過Lua調用C動態鏈接庫。實際上,調用方法基本上只是Lua與C之間的問題,與LaTeX幾乎無關。

    這裏介紹的方法需要使用LuaJIT,請到LuaJIT官網下載安裝,上面介紹得很清楚,這裏不再贅述。

    調用方法的關鍵在於C源代碼的編寫方式,所以我們將首先介紹這個。我用的構建工具是CMake,在項目文件夾內,有src與build兩個文件夾,主文件main.c放在src文件夾內。CMakeLists.txt文件在項目文件夾內。結構如下:

項目文件夾
├── build
│       └── 
├── CMakeLists.txt
└── src
      └── main.c

    下面列出文件源碼


操作系統:Ubuntu 18.04

LaTeX編輯工具:TeXstudio 2.12.6

LaTeX編譯方式:LuaLaTeX

構建工具:CMake 3.16.4

C編譯器:gcc 7.4.0

Lua解釋器:LuaJIT 2.0.5


文件1:CMakeLists.txt

cmake_minimum_required(VERSION 3.0)

set(project_name plotpen)

# 設置庫文件的生成目錄爲工程頂層目錄
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR})

project(${project_name})

aux_source_directory(src/ DIR_SRCS)

add_library(${project_name} SHARED ${DIR_SRCS})

# 去掉默認加上的lib前綴
set_target_properties(${project_name} PROPERTIES PREFIX "")

文件2:main.c

// 開源中國,陸巍
#include "/usr/local/include/luajit-2.0/lauxlib.h"
#include "/usr/local/include/luajit-2.0/lua.h"
#include "/usr/local/include/luajit-2.0/lualib.h"
#include <string.h>
#include<stdlib.h>

// 加上聲明,以免編譯時出現警告
void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup);

static int Hello(lua_State *L)
{
   char *str0 = "\\noindent We are here\\\\";
   const char * latexStr = luaL_checkstring(L, 1) ;
   char *str1 = (char *) malloc(strlen(str0) + strlen(latexStr));
   strcpy(str1, str0);
   strcat(str1, latexStr);
   lua_pushstring(L, str1);
   free(str1);
   return 1;
}

// 註冊函數
static luaL_Reg RegLibs[] = {
    {"Hello", Hello},
    {NULL, NULL}};

// 這裏的函數名luaopen_plotpen是有固定格式的,格式爲:luaopen_你的庫名
int luaopen_plotpen(lua_State *L)
{
   lua_newtable(L);
   luaL_setfuncs(L, RegLibs, 0);
   return 1;
}

    編譯後會在項目文件夾內出現名爲plotpen.so的動態鏈接庫文件。

說明:

  1. CMakeLists.txt文件中的最後一行語句是去掉庫文件的lib前綴,只有去掉後才能正常調用。包括C++動態鏈接庫也是如此處理。
  2. test.c代碼中注意luaopen_plotpen函數,如果你的庫文件名爲test.so,那麼這個函數的名稱就要改爲luaopen_test,以此類推。
  3. 傳入的數據並非只是示例中的字符串,還可以傳入其他類型的數據,例如luaL_checkint,可在網上查詢相關資料,或者看IDE上的提示。我使用的是VSCode,包含那幾個LuaJIT的頭文件後,上面就會有相關函數的提示。
  4. 爲了方便查看效果,最好先安裝Lua,先在終端上調用生成的庫文件看看結果,如果有錯也可以察看錯誤原因。

    下面是LaTeX方面的文件。

文件1:test.tex

\documentclass{article}
%  開源中國,陸巍
\usepackage{ctex}% 中文支持
\usepackage{geometry}% 用於頁面設置
\usepackage[dvipsnames, svgnames, x11names]{xcolor} % 顏色支持
\usepackage{luacode}
\usepackage{tikz}
\usepackage{fancyvrb}

\usepackage{metasequoia}

% 設置爲A4紙,並按照MSOffice的默認尺寸設置四周邊距
\geometry{
	a4paper,
	left = 3.17cm,
	right = 3.17cm,
	top = 2.54cm,
	bottom = 2.54cm
}

\begin{document}
	\section{通過lua調用C動態鏈接庫}
	
  \pic[We are LINUX]{}

\end{document}

文件2:metasequoia.sty(自定義宏包文件)

%  開源中國,陸巍
\NeedsTeXFormat{LaTeX2e}[2007/10/19]%
\ProvidesPackage{metasequoia}[2020/02/29]%

\newcommand{\pic}[1][]{
  \renewcommand{\baselinestretch}{1.0}%
  \luaexec{%
    local test = require("plotpen")
    str = test.Hello("#1")
    tex.sprint(str)
  }%
}

執行結果如下:

通過lua調用C動態鏈接庫示例

說明:

  1. 本例中把lua調用單獨用一個自定義宏包來完成,裏面定義了新命令來調用。從這個自定義宏包的文件上,可以看到lua調用c動態鏈接庫的方法(調用C++也是這樣),也可以看到LaTeX宏包的定義方式。
  2. 最好把鏈接庫文件放在tex文件所在同一目錄下,否則可能找不到。這一點我沒有去查找原因,先這樣用着。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章