nodejs与c语言交互应用实例

nodejs与c/c++交互目前主流的方式有两种,node addon c++ 和 node-ffi .

1、node addon c++

1)nodejs从c语言读取数据

addon.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

typedef struct
{
    double lon;
    double lat;
}gps_info_t;

gps_info_t* gps;


void get_gps_shm_init(void)
{
    gps = (gps_info_t *)malloc(sizeof(gps_info_t));
}

Napi::Object CreateObject(const Napi::CallbackInfo& info) {
    Napi::Env env = info.Env();
    Napi::Object obj = Napi::Object::New(env);
    
    gps->lon = 55.5;
    gps->lat = 66.6;

    printf("send lon: %f\n", gps->lon);
    printf("send lat: %f\n", gps->lat);

      obj.Set(Napi::String::New(env, "lon"), gps->lon);
    obj.Set(Napi::String::New(env, "lat"), gps->lat);

      return obj;
}

Napi::Object Init(Napi::Env env, Napi::Object exports) {
    get_gps_shm_init();
      return Napi::Function::New(env, CreateObject, "createObject");
}

NODE_API_MODULE(addon, Init)

addon.js

var addon = require('bindings')('addon');

var obj = addon('gps');

console.log(obj.lon);
console.log(obj.lat);

module.exports.obj = obj;

 

2)nodejs向c语言写数据

addon.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

typedef struct
{
    char *user_name;
    char *passwd;
    char *dev_id;
}user_info_t;

user_info_t* user;

void put_user_info_shm_init(void)
{
    user = (user_info_t *)malloc(sizeof(user_info_t));
    user->user_name = (char*)malloc(32*sizeof(char));
    user->passwd = (char*)malloc(32*sizeof(char));
    user->dev_id = (char*)malloc(32*sizeof(char));
}

Napi::Object CreateObject(const Napi::CallbackInfo& info) {
    Napi::Env env = info.Env();
    Napi::Object obj = Napi::Object::New(env);

    memset(user->user_name, 0, 32); 
    memset(user->passwd, 0, 32); 
    memset(user->dev_id, 0, 32); 
    memcpy(user->user_name, info[0].ToString(), 32);
    memcpy(user->passwd, info[1].ToString(), 32);
    memcpy(user->dev_id, info[2].ToString(), 32);

    printf("recv user info (user_name): %s\n", user->user_name);
    printf("recv user info (passwd): %s\n", user->passwd);
    printf("recv user info (dev_id): %s\n", user->dev_id);    

      return obj;
}

Napi::Object Init(Napi::Env env, Napi::Object exports) {
    put_user_info_shm_init();
      return Napi::Function::New(env, CreateObject, "createObject");
}

NODE_API_MODULE(addon, Init)

addon.js

var addon = require('bindings')('addon');

var user_info = {
    user_name = 'zdd';
    passwd = '123';
    dev_id = '65535'
}

var obj = addon(user_info.user_name,user_info.passwd,user_info.dev_id);

module.exports.user_info = user_info;

nodejs的C/C++拓展,将c/c++源码编译成js模板库

ubuntu下编译

node-gyp configure
node-gyp build

node addon.js

交叉编译
export CC=arm-linux-gnueabihf-gcc
export CXX=arm-linux-gnueabihf-g++
export LD=arm-linux-gnueabihf-ld
export RAINLIB=arm-linux-gnueabihf-rainlib
export AR=arm-linux-gnueabihf-ar
export LINK=arm-linux-gnueabihf-g++
node-gyp configure --arch=arm
node-gyp build

node addon.js

 

2、node-ffi

1)nodejs从c语言读取数据

factorial.c

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

#if defined(WIN32) || defined(_WIN32)
#define EXPORT __declspec(dllexport)
#else
#define EXPORT
#endif

typedef struct
{
    double lon;
    double lat;
}gps_info_t;

gps_info_t* gps;

void get_gps_shm_init(void)
{
    gps = (gps_info_t *)malloc(sizeof(gps_info_t));
}

EXPORT gps_info_t* get_gps_info(void) {
  get_gps_shm_init();
  gps->lon = 55.5;
  gps->lat = 55.5;return gps;
}

factorial.js

var ffi = require('../node-ffi-master/')
var refStruct = require('ref-struct');
var refArray = require('ref-array');
var ref = require('ref');

//gps date struct
var gps = refStruct({
    'lon':ref.types.double,
    'lat':ref.types.double,
});

var gpsStructArrayType = refArray(gps);
var gps_info = gpsStructArrayType(10);

var libfactorial = ffi.Library('./libfactorial', {
  'get_gps_info': [ gpsStructArrayType, [ 'void' ] ],
});

gps_info = libfactorial.get_gps_info(0)

console.log('Your output: ' + gps_info[0].lon)
console.log('Your output: ' + gps_info[0].lat)

 

2)nodejs向c语言写数据

factorial.c

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

#if defined(WIN32) || defined(_WIN32)
#define EXPORT __declspec(dllexport)
#else
#define EXPORT
#endif

typedef struct
{
    char *user_name;
    char *passwd;
    char *dev_id;
}user_info_t;

user_info_t* user;

void put_user_info_shm_init(void)
{
    user = (user_info_t *)malloc(sizeof(user_info_t));
    user->user_name = (char*)malloc(32*sizeof(char));
    user->passwd = (char*)malloc(32*sizeof(char));
    user->dev_id = (char*)malloc(32*sizeof(char));
}

EXPORT void put_user_info(user_info_t* user_info) {
  put_user_info_shm_init();
  printf("get userinfo(user_name):%s",user_info->user_name);
  printf("get userinfo(user_name):%s",user_info->passwd);
  printf("get userinfo(user_name):%s",user_info->dev_id);
}

 factorial.js

var ffi = require('../node-ffi-master/')
var refStruct = require('ref-struct');
var refArray = require('ref-array');
var ref = require('ref');

//ui date struct
var user = refStruct({
    'user_name':'string',
    'passwd':'string',
    'dev_id':'string',
});

var userStructArrayType = refArray(user);
var user_info = userStructArrayType(1);

user_info[0].user_name = 'zdd';
user_info[0].passwd = '123';
user_info[0].dev_id = '65535';

var libfactorial = ffi.Library('./libfactorial', {
  'put_user_info': [ 'void', [ userStructArrayType ] ]
});

libfactorial.put_user_info(user_info)

console.log('Your input: ' + user_info[0].user_name)
console.log('Your input: ' + user_info[0].passwd)
console.log('Your input: ' + user_info[0].dev_id)

gcc / arm-linux-gnueabihf-gcc -shared -fpic factorial.c -o libfactorial.so

node factorial.js

 

上面两种方式写了个demo放在github上了

https://github.com/zhoudd1/nodejs_call_c_cc

 

3、还有一种小众化的方式

通过child_process 方式调用EXE进程来实现数据交互。

var cp= require('child_process');
//同步的方式

letout = cp.execFileSync("testdll.exe", ["arg1","arg2"],{});


//异步的方式

cp.execFile("testdll.exe", ["arg1","arg2"], {}, (error, stdout, stderr) => {
    console.log(stdout);
})
 

这种方式NODE 会接管stdout 和 stderr ,exe中把结果通过 printf 输出。
缺点:需要先生成EXE,EXE 中调用 DLL/so 并且返回结果。
优点:不需要配置 FFI,不受DLL/so 的影响

更多细节

 https://www.cnblogs.com/chyingp/p/node-learning-guide-child_process.html

 https://blog.csdn.net/zeping891103/article/details/52230175

 

posted @ 2018-04-20 14:49  dong1  阅读(9278)  评论(0编辑  收藏  举报