LuaLaTeX调用外部Lua程序与C语言编写的动态链接库

  在LuaLaTeX编译方式下,虽然可以直接在tex文件中编写Lua代码,但会受到LaTeX的影响,编写中并不是很便利。所以我在实际使用中一般都把Lua代码的主体部分放在LaTeX的外部,这样可以完全按照以往的编程习惯去编写。我以前所在的公司,曾经在机器人运动控制系统中使用过Lua,但因为我没有负责那一部分,所以只是知道有Lua这么个脚本语言,并没有实际编写过。这几天才开始学习编写Lua代码,所以还有很多不足,请多多体谅。下面介绍一下我的用法。

1、开发环境

  • 操作系统:Ubuntu 16.04 64位桌面版

  • LaTeX工具:TeXstudio 2.10.8

  • 编译方式:LuaLaTeX

  • Lua编辑工具:Visual Studio Code 1.30.2

  • Lua插件:vscode-lua 0.12.4

2、LaTeX中使用Lua

  我使用的宏包是luacode。在安装TeXstudio后,我顺手就安装了texlive-all,这个宏包包含在里面。在TeXstudio中,右键点击\uspackage{luacode}弹出的菜单中,可以打开luacode的说明文档。
  luacode中提供了四种使用Lua代码的命令,他们的差别如下表:

\luadirect \luaexec \luacode \luacode*
Yes Yes Yes No
单反斜杠 \string\ \string\ \string\ Just \
双反斜杠 \string\\ \\ \\ \\
波浪号 \string ~ ~ ~
# \string# \# #(or \#) #
百分号 No easy way \% %(or \%) %
TEX注释 Yes Yes No No
Lua的行注释 No NO Yes Yes

从表中可以看到不同命令的差异。我通常使用的是\luaexec命令。调用方式就是在\luaexec{}的大括号内编写Lua代码。通过以上命令来编写Lua代码,一方面因为受到LaTeX格式的影响,会有很多不便;另一方面也不符合我们的软件设计原则。所以需要把Lua的归给Lua,不要全都放在这里,这里仅保留调用代码。

3、调用外部Lua代码

  调用方式很简单,一般有两种。一种是用require,另一种是用dofile。但要注意的是package.path在LaTeX中好像并没有用,我的代码在Lua命令行模式下调用没有问题,在LaTeX中就不行,具体原因还不清楚。现在我是在require中直接加上路径。例如:

% ------ 类图 ------
\newcommand{\umlClass}[2][]{%
  \luaexec{%
    require "lua/uml_class"
    local umlClass = UmlClass:new(nil, "#1", "#2")
    tex.sprint(umlClass:Draw())
  }%
}%

  其中,uml_class.lua(调用时不用加扩展名)文件放在tex所在文件夹的子目录lua中。传入的参数#1与#2一定要放在双引号里面。输出方式就是tex.sprint(…)。

4、调用C编写的动态链接库

  这方面与单纯Lua下调用差不多,网上有很多例子,我就不多说了,直接贴上代码。

**c 源代码:test.c **

// CSDN 陆巍的博客 https://blog.csdn.net/weixin_44420912/article/details/86352615
#include <stdio.h>
#include "/usr/local/include/luajit-2.0/lua.h"
#include "/usr/local/include/luajit-2.0/lauxlib.h"
#include "/usr/local/include/luajit-2.0/lualib.h"

// 加上声明,以免编译时出现警告
void luaL_setfuncs (lua_State* L, const luaL_Reg* l, int nup);

static int Area(lua_State *L) {
  double radius = luaL_checknumber(L, 1);
  lua_pushnumber(L, 3.1416 * radius * radius);
  return 1;
}

static int Hello(lua_State *L) {
  char* str1= {"Hello, it's me."};
  lua_pushstring(L, str1);
  return 1;
}

static luaL_Reg RegLibs[] = {
  {"Area", Area},
  {"Hello", Hello},
  {NULL, NULL}
};

// 这里的函数名luaopen_test是有固定格式的,格式为:luaopen_你的库名
int luaopen_test(lua_State* L) {
  lua_newtable(L);
  luaL_setfuncs(L, RegLibs, 0);
  return 1;
}

  我的Lua是使用sudo apt install命令安装的,版本是5.2.4。在不同版本下,以上代码还有些不同,可参考网上文章介绍,比较多,不说了。这里只是把我实际验证过的代码发上来。

把test.c文件编译为动态链接库

gcc -fPIC -shared -o test.so test.c

  我的gcc版本是5.4.0。

LaTeX中的调用代码

// CSDN 陆巍的博客 https://blog.csdn.net/weixin_44420912/article/details/86352615
\documentclass{article}%
%
\usepackage{ctex}%
\usepackage{luacode}%
%
\setlength{\parindent}{0pt}%
%
\begin{document}%
%
LuaLaTeX使用Lua代码,Lua调用C动态链接库示例:\\\\%
%
\luaexec{%
  local test = require("test")
  str = "字符串示例:" .. test.Hello() .. "\\\\"
  tex.sprint(str)
  str = "数值计算示例,面积: " .. test.Area(6)
  tex.sprint(str)
}%
%
\end{document}%

效果如下:
lua调用c动态链接库示例

  通过以上方式,我们就把LaTeX、Lua与C联系在了一起,这样一来,对于程序员来说可以发挥的空间就很大了。

  这段时间我就在用Lua来编写在LaTeX中绘制UML图形的代码,原来是在XeLaTeX编译方式下,用的办法主要是pgf那一套(不过,通用性比Lua的强),但始终不怎么方便,所以这几天改用Lua来写,正在编写中。下面放一张图片:
uml绘制示例
  项目已经放在码云中,等编得差不多了再发给大家看。Lua的文字处理功能不错,暂时我在LaTeX的使用中还用不到C语言来编写代码。

猜你喜欢

转载自blog.csdn.net/weixin_44420912/article/details/86352615