在具体的electron项目中,需要调用本地c++编写的dll函数,函数中国有多个out parameter,但是各种尝试,发现最新的如下版本不支持引用传递
"dependencies": {
"ffi-napi": "^2.5.0",
"ref-napi":"^2.0.3"
}
"devDependencies": {
"@types/ffi-napi": "^3.0.1",
"@types/ref-napi":"^3.0.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();
MYLIBDLL float Add(float plus1, float plus2);
MYLIBDLL int StrLength(char * str);
MYLIBDLL void changeStr(char* str);
MYLIBDLL void changeNum(int* num);
MYLIBDLL void setCallBack(void (*)(int, char* str));
#endif
myhello.cpp
#include "myhello.h"
#include<stdlib.h>
#include <iostream>
using namespace std;
float Add(float plus1, float plus2)
{
float add_result = plus1 + plus2;
return add_result;
}
char* Hello()
{
return "Hello This is Cpp Addon";
}
int StrLength(char* str)
{
return strlen(str);
}
char* outStr = "hello world";
void changeStr(char* str) {
char src[] = "xiaojiayu";
strcpy(str, src);
}
int outNumber = 10;
void changeNum(int* num) {
num = &outNumber;
}
void setCallBack(void (*func)(int, char* str)) {
func(12, "yjing");
}
编译出来的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输出结果如下
D:\study\electron\electron-quick-start\preload.js:25 myHelloLib add = 7
D:\study\electron\electron-quick-start\preload.js:29 myHelloLib Hello = Hello This is Cpp Addon
D:\study\electron\electron-quick-start\preload.js:31 id: 12name: yjing
D:\study\electron\electron-quick-start\preload.js:37 actrualStr = xiaojiayu
D:\study\electron\electron-quick-start\preload.js:41 actualNum = 0
D:\study\electron\electron-quick-start\preload.js:27 aync res = 11
注意这里的name只是暑促了y,应为c++回调的字符串包含了特殊字符’\0’表示该字符串结束的位置,这点应该特别注意下。另外需要注意的是ffi-napi本身是支持应用传递的,如例子所示,但是一定要注意
native端要使用类似strcpy的函数来给传入的参数赋值,这个可以参考这篇文章,how to get value of ''c #397