在具体的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链接地址,以上!