ffi动态链接库的使用
最进项目中使用到了socketproc通信,但是这样有一点不是很好,必须单独启动一个进程来执行代码中的shell命令,后面想在nginx+lua的环境下使用openresty中的lua-resty-shell,但是在后续阅读源码说明的时候发现依赖关系过于复杂,会导致引入的openresty模块越来越堵。但是发现归根结底是对ffi库的调用,什么是ffi库?
说白一点:ffi动态库就是lua语言调用底层C语言的一系列接口,而ffi动态库日空了非常方便的编码风格,来使用完成自己的功能。来看一下如何使用ffi库。
首先下载源码到自己的环境中进行编译。需要注意的是这个插件根据环境的不同生成的动态库不能相互使用的,楼主在过程中就烦了这个错误,将ubuntu环境下的动态库移动到centOS下使用失败。
首先make 会发现有两个找不到的,这时候就需要你手动更改Makefile中的PKG_CONFIG_PATH和lua的路径,改正之后make 成功,就会看到生成了ffi.so
然后将动态库拷贝到nginx的conf同一级目录下的lualib路径下,再将此路径添加到lua的cpath中,就可以使用了,就像下面一样:
package.cpath= "/usr/local/nginx-1.16.0/lualib/?.so;;"..package.cpath local ffi = require("ffi") local ffiShell = ffi.load("shellTest") ffi.cdef[[ struct dummy{}; double sqrt(double x); int gethostname(char *name,size_t len); char* Run(const char* cmd); ]] local dat = ffiShell.Run('ls -al /tmp') ngx.print(ffi.string(dat)) local int_t = ffi.typeof("int") local char_arr_t = ffi.typeof("char[?]") local a_int = ffi.new(int_t) local char_arr=char_arr_t(10) local x = ffi.C.sqrt(5) ngx.print(x) ffi.fill(char_arr,10) ffi.C.gethostname(char_arr,10) --ngx.print(char_arr) ngx.print(ffi.string(char_arr)) --ngx.print(char_arr[0]) ngx.say(" call ffi.so!") --ngx.say(ffiShell.Run("ls -al ")) --ffi.C.system("ls -al /usr/local")
shellTest是楼主自己使用C语言中的popen函数写的一个调用shell命令接口的动态链接库
#include "shellTest.h" char* Run(const char* shellCmd){ /* int ret = system(shellCmd); if(ret < 0){ char errInfo[128]; sprintf(errInfo,"system call shellCmd error,ret:%d",ret); return errInfo; }else if(ret == 0){ return "system fork failed"; }else{ return "shellCmd call successful!"; } */ char buf[1024]; FILE *fp=popen(shellCmd,"r"); fgets(buf,sizeof(buf),fp); //fscanf(fp,"%s",buf); //printf("%s",buf); pclose(fp); return buf; }
头文件
#ifndef __SHELLCMD_H #define __SHELLCMD_H #include <stdio.h> #include <stdlib.h> char* Run(const char* shellCmd); #endif
可能贴出来的代码有问题,需要大家在使用的时候进行简单的修改
作者:first_semon
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。如有问题,欢迎交流