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文件所在同一目录下,否则可能找不到。这一点我没有去查找原因,先这样用着。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章