JavaScript调用C库
本文介绍通过ffi方式调用C动态库
系统:ubuntu16.04 64bit
一、环境安装
-
安装js运行环境
- V17.3.0 地址:https://nodejs.org/dist
- wget https://nodejs.org/dist/v17.6.0/node-v17.6.0-linux-x64.tar.xz
- 解压tar xvf node-v17.6.0-linux-x64.tar.xz
- sudo mv node-v17.6.0-linux-x64 /usr/local/nodejs
- 添加环境变量 vi ~/.bashrc (添加后重启终端窗口)
export PATH=$PATH:/usr/local/nodejs/bin export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/nodejs/lib
-
安装ffi相关
- 设置源:npm config set registry https://registry.npmmirror.com (淘宝)
- npm config set python /usr/bin/python3 (python>3.6.0)
- npm install node-gyp
- npm install ffi-napi
- npm install ref-napi
- npm install ref-array-napi
- npm install ref-struct-napi
二、测试代码
-
c代码test.c–>编译出动态库libtest.so
#include <stdio.h> typedef struct {int id;char* name;double height;int score[10];int score_size; }userStruct; typedef void (*callback)(int val); static char char_point[64] = ""; int api_int(int a, int b) {return a + b; }double api_double(double a, double b) {return a + b; }char* api_char_point(char* a, char* b){memset(char_point, 0, sizeof(char_point));sprintf(char_point, "%s %s", a, b);return char_point; }int api_int_array(int* a, int size){int i = 0; for(i = 0; i < size; i++){a[i] = i;}return 0; }int api_struct(userStruct user){int i = 0;char buf[128] = "";printf("C Print score_size:%d\n", user.score_size);for(i = 0; i < user.score_size; i++){printf("C Print i:%d, score:%d\n",i, user.score[i]);sprintf(buf, "%s %d", buf, user.score[i]);}printf("C Print id:%d name:%s height:%f socre:%s\n", user.id, user.name, user.height, buf);return 0; } void api_callback(callback cb){cb(1); } -
js代码 test.js
const ffi = require('ffi-napi'); const ref = require('ref-napi'); const refArray = require('ref-array-napi') const StructType = require('ref-struct-napi'); const IntArray10 = refArray(ref.types.int, 10); const userStruct = StructType({id: 'int',name: 'string',height: 'double',score: IntArray10,score_size: 'int' });const rockeyInterface = {'api_int':['int', ['int', 'int']],'api_double':['double', ['double', 'double']],'api_char_point':['string', ['string', 'string']],'api_int_array':['int', ['pointer', 'int']],'api_struct':['int', [userStruct]],'api_callback':['void', ['pointer']] }let libtest = new ffi.Library('./libtest.so', rockeyInterface); //int test console.log("int result:", libtest.api_int(1, 2)); //double test console.log("double Result:", libtest.api_double(1.1, 1.2)); //char* test console.log("char* result:", libtest.api_char_point('hello', 'world')); //int array test let arraySize = 10; let arrayBuf = Buffer.alloc(arraySize* Int32Array.BYTES_PER_ELEMENT); console.log(typeof arrayBuf); console.log(arrayBuf.length); if(libtest.api_int_array(arrayBuf, arraySize) == 0){let arrayResult = new Int32Array(arrayBuf.buffer);console.log("int array result:", arrayResult); } //struct test let user = new userStruct(); user.id = 101; user.name = 'hsl'; user.height = 1.78; user.score_size = 10; user.score = new IntArray10(); for(var i = 0; i < user.score_size; i++){user.score[i] = i+1; } let ret = libtest.api_struct(user); console.log("struct result:", ret);//callback test const callback = ffi.Callback('int', ['int'], function(value){console.log("callback result:", value); }); libtest.api_callback(callback); -
运行:node test.js
附:
python3升级下载:wget https://www.python.org/ftp/python/3.7.9/Python-3.7.9.tgztar xvf Python-3.7.9.tgzcd Python-3.7.9./configuremake && sudo make installsudo rm /usr/bin/python3sudo ln -s /usr/local/bin/python3 /usr/bin/python3