问题是这样的,因为nodejs 不能直接操作硬件相关的东西,所以我通过c++写了一个dll,导出函数给nodejs调用,以下是我的c++相关代码
extern "C" {
EXPORT const char* sayBye();
}
const char* sayBye() {
string name = "java 最好的语言";
return name.c_str();
}
const ffi = require('ffi-napi');
const myLib = ffi.Library('dll/test-plugin.dll', {
'sayBye':['string',[]]
});
var result=myLib.sayBye()
console.log('result',result)
引用chatgpt部分指引作答:
这个报错信息是关于 Electron 的安全警告,提示你的应用程序的 Content Security Policy(内容安全策略)可能存在问题。它指出你的应用程序的渲染进程(renderer process)的 Content Security Policy 要么没有设置,要么启用了 "unsafe-eval",从而给用户带来了不必要的安全风险。
这个报错与你的代码中调用 C++ DLL 的乱码问题没有直接关系。不过,我注意到你的 C++ 代码中有一个潜在的问题可能导致乱码。
在你的 C++ 代码中,你将一个字符串赋值给了 name 变量,然后通过 name.c_str() 返回了一个指向该字符串的指针。然而,在 C++ 中,局部变量的生命周期在其所在的作用域结束时就会结束,这意味着 name 变量在函数 sayBye 结束时会被销毁,返回的指针将变为无效指针。因此,在 Node.js 中使用这个指针可能会导致未定义的行为和乱码。
要解决这个问题,你可以考虑使用动态内存分配,例如使用 new char[] 来存储字符串,并在使用完之后手动释放内存,确保指针有效。下面是一个修改后的示例:
const char* sayBye() {
string name = "java 最好的语言";
char* namePtr = new char[name.size() + 1];
strcpy(namePtr, name.c_str());
return namePtr;
}
然后,在 Node.js 中,你需要注意释放内存,以防止内存泄漏。你可以使用 ffi 模块提供的 ffi.Callback() 方法来定义一个回调函数,在回调函数中释放内存。下面是一个修改后的示例:
const ffi = require('ffi-napi');
const myLib = ffi.Library('dll/test-plugin.dll', {
'sayBye': ['string', []]
});
const releaseMemory = ffi.Callback('void', ['pointer'], (ptr) => {
// 释放内存
ffi.Library('msvcrt', {
'free': ['void', ['pointer']]
}).free(ptr);
});
myLib.sayBye.async = ['string', []];
myLib.sayBye.post = releaseMemory;
myLib.sayBye((err, result) => {
if (err) {
console.error(err);
} else {
console.log('result', result);
}
});
这个示例中,我们使用 ffi.Callback() 定义了一个回调函数 releaseMemory,该函数接受一个指针作为参数,并在其中调用 msvcrt 库的 free 函数释放内存。然后,通过将 releaseMemory 函数传递给 myLib.sayBye.post,在调用 sayBye 之后自动释放内存。
这只是一个潜在的问题,可能导致乱码的原因之一。如果你仍然遇到乱码问题,请提供更多关于问题的详细信息,以便更好地理解和帮助你解决问题。
1、以管理员权限打开cmd,输入快捷命令:npm install --global --production windows-build-tools
这期间可能会遇到visual studio(C++工具包)安装不成功的情况:
这种情况下可以使用离线安装的方式(通过以下链接下载离线安装包):
https://pan.baidu.com/s/1Nh7cCrqyroEMH90HUYbvfw 提取码:5251
直接安装:
安装完成之后查看python是否安装成功:
这说明安装成功,安装成功之后将python的路径添加到环境变量中:
2、安装.net环境地址(可以选择4.6.2包)
.NET SDKs downloads for Visual Studio
3、安装上述各环境之后就可以安装ffi了,我这边安装的ffi版本是2.3.0的,使用命令
cnpm install ffi@2.3.0,相对应类型转换的插件版本如下:
"ffi": "^2.3.0",
"ref": "^1.3.5",
"ref-array": "^1.2.0",
"ref-struct": "^1.1.0",
4、安装上述环境的过程中遇到了很多问题,捣鼓了很久才把整个环境安装好,环境安装好之后调用动态库的过程也遇到很多问题,下面记录下自己在安装和调用的过程中遇到的一些问题:
(1)报语法错误:
上面的截图说是啥语法错误,在网上找了很多资料,很多说是因为nodejs版本高了的问题,于是我将nodejs版本降低,降低到了v11.10.0,然后再安装,最后成功了:
(2)font.scss报错:
上面截图的错误可以通过提示重新安装一遍sass,命令如下:
npm rebuild node-sass
(3)Error:Cannot find module 'ffi'
上面的提示需要重新安装一遍ffi
(4)Error: A dynamic link library (DLL) initialization routine failed
上面报错问题需要执行下面的命令重新rebuild:
1、npm config set python "C:\Python27\python.exe"
2、npm config set node_gyp "C:\Users\10376\AppData\Roaming\npm\node_modules\node-gyp\bin\node-gyp.js"
3、重新编译electron:./node_modules/.bin/electron-rebuild
4、.\node_modules\.bin\electron-rebuild.cmd
(5)调用动态库时报各种编码错误:
针对nodejs通过ffi-napi调用c++ dll函数时出现乱码问题,我可以提供如下解决方案:
确认编码方式:首先需要确认dll中字符串的编码方式,如果是UTF-8编码,则需要在node.js中使用utf-8编码的字符串。可以使用Buffer.from()方法进行转换,例如Buffer.from("你好","utf-8")。如果dll中字符串编码为GBK,则需要使用iconv-lite等模块进行转换。
确认数据类型:在ffi-napi调用C++函数时,需要确认参数类型,特别是指针类型。如果dll中参数类型是char,则在nodejs中需要使用Uint8Array类型,如果是wchar_t,则需要使用Uint16Array类型。同时,需要使用ref.refType()方法获取指针类型对应的类型。
字符集转换:当node.js中使用的字符集与dll中不一致时,需要进行字符集转换。可以使用iconv-lite等模块进行转换,具体方法是先将字符串用Buffer.from()方法转为Buffer,然后使用iconv-lite进行转换,最后再将结果用Buffer.toString()转为字符串。
确认动态库文件:有时候dll文件名中包含了中文或特殊字符,导致node.js无法正确加载,此时需要将dll文件名改为英文或数字等正常字符。
以上就是解决nodejs通过ffi-napi调用c++ dll函数时出现乱码问题的一些解决方案,根据具体情况进行选择和调整。