关于ffi-napi结合ref-napi调用dll的经验总结

在具体的electron项目中,需要调用本地c++编写的dll函数,函数中国有多个out parameter,但是各种尝试,发现最新的如下版本不支持引用传递

"dependencies": {
	"ffi-napi": "^2.5.0",
 	"ref-napi":"^2.0.3"
 }

"devDependencies": {
    "@types/ffi-napi": "^2.4.1",
    "@types/ref-napi":"^1.4.1"
}

尽管node-ffi文档Node FFI Tutorial写了可以支持的,不知道是不是ref-napi和node-ffi有什么差异,导致的,反正我这里就是不支持的,尝试使用如下node-ffi依赖(node-ffi不支持node10以上版本)

 "ffi": "github:lxe/node-ffi#node-12",
 "ref": "github:lxe/ref#node-12"

但是无论使用npm还是yarn都无法正常的install,另外我的项目是基于typescript的这两个依赖看起来也没有对应的@types依赖,故放弃。

最后无赖还是采用Node FFI Tutorial文档中的回调函数来解决多参数返回的问题,c++代码如下
myhello.h

#pragma once
#ifndef TestDll_H_
#define TestDll_H_
#ifdef MYLIBDLL
#define MYLIBDLL extern "C" _declspec(dllimport)
#else
#define MYLIBDLL extern "C" _declspec(dllexport)
#endif
MYLIBDLL char* Hello(char* temp);
MYLIBDLL float Add(float plus1, float plus2);
MYLIBDLL int StrLength(char* str);
MYLIBDLL int* init();
MYLIBDLL int get(int* base); 
MYLIBDLL void release(int* base);
MYLIBDLL void selectball(void (*ball)(int, char*));
//You can also write like this:
//extern "C" {
//_declspec(dllexport) int Add(int plus1, int plus2);
//};
#endif#pragma once

myhello.cpp

#include "stdint.h"
#include "stdlib.h"
#include "myhello.h"
#include 
using namespace std;
float Add(float plus1, float plus2)
{
	float add_result = plus1 + plus2;
	return add_result;
}

const char* a = "hello";
char* Hello(char* temp)
{
	char* text = "hello from yjing hh";
	temp = text;
	temp = "ni hao ";
	printf(temp);
	return temp;
}

int StrLength(char* str)
{
	return strlen(str);
}

int* init() 
{
	int* p = (int*)calloc(10,sizeof(int));
	p[0] = 33;
	return p;
}

int get(int* base)
{	
	return *base;
}

void release(int* base) {
	free(base);
}


void selectball(void (*ball)(int, char*))
{
	printf("选择什么球?");
	int id = 0;
	char name[] = "y\0jing";
	ball(id,name);
}

编译出来的dll为myhello.dll,对应的通过如下ts代码调用myhello.dll

var myHelloLib = ffi.Library('../../dll/myhello.dll', {
      'Hello': ['string', ['string']],
      'StrLength': ['int', ['string']],
      'init': ['int*', []],
      'get': ['int', ['int*']],
      'release': ['void', ['int*']],
      'selectball': ['void', ['pointer']]
    })
    const buffer = new Buffer(20);
    buffer.writeCString('wo shi da ying', 0);
    var retBuffer = myHelloLib.Hello(buffer);
    console.log('after call Hello buffer' + ref.readCString(buffer, 0));
    console.log('this is Hello ' + myHelloLib.Hello(buffer));

    var idx = myHelloLib.init()
    console.log("I get id")
    console.log(myHelloLib.get(idx))
    console.log('realse ' + myHelloLib.release(idx))

    console.log('StrLength = ' + myHelloLib.StrLength(retBuffer));


    var callback = ffi.Callback('void', ['int', 'string'],
      function (id, name) {
        console.log("id: ", id);
        console.log("name: ", name);
      });
    myHelloLib.selectball(callback);

console输出结果如下

after call Hello bufferwo shi da ying
dll-io.ts:104 this is Hello ni hao 
dll-io.ts:107 I get id
dll-io.ts:108 33
dll-io.ts:109 realse null
dll-io.ts:111 StrLength = 7
dll-io.ts:116 id:  0
dll-io.ts:117 name:  y

注意这里的name只是暑促了y,应为c++回调的字符串包含了特殊字符’\0’表示该字符串结束的位置,这点应该特别注意下

后续会补上myhello.dll链接地址,以上!

你可能感兴趣的:(web,javascript,C++)