一、为什么需要使用DLL

  • 需要使用系统 API 操作或扩展应用程序;
  • 需要调用第三方的接口API,特别是与硬件设备进行通信,而这些接口 API 基本上都是通过 C++ 动态链接库(DLL)实现的;
  • 需要调用C++实现的一些复杂算法等。

二、node-ffi 是什么

node-ffi:Node.js Foreign Function Interface

node-ffi is a Node.js addon for loading and calling dynamic libraries using pure JavaScript. It can be used to create bindings to native libraries without writing any C++ code. It also simplifies the augmentation of node.js with C code as it takes care of handling the translation of types across JavaScript and C, which can add reams of boilerplate code to your otherwise simple C. See the example/factorial for an example of this use case.

WARNING: node-ffi assumes you know what you're doing. You can pretty easily create situations where you will segfault the interpreter and unless you've got C debugger skills, you probably won't know what's going on.

上面是 node-ffi 的介绍,英语不好,就不翻译了。

三、electron 使用 node-ffi

使用上一篇文章里的项目,在 package.json 的 dependencies 节点上加上node-ffi 依赖:

"dependencies": {
"electron": "^1.6.11",
"ffi": "2.2.0"
}

然后安装缺失的 npm 包(参考之前的文章),注意,安装 ffi npm 包之前需要安装 python2.7,否则 ffi 会编译总是失败,导致安装不成功,具体安装参考:https://github.com/nodejs/node-gyp#installation

安装完成后,在 app.js 文件第一行中添加如下代码:

const ffi = require('ffi')

然后运行程序,出现如下错误:

参考资料:https://github.com/electron/electron/blob/master/docs-translations/zh-CN/tutorial/using-native-node-modules.md,原来是需要把 ffi 重新编译为适合 electron的模块。

打开 nodejs 命令行窗口,先执行如下命令:

set python=python安装路径\python.exe

设置 python 的路径,切换到项目目录,然后执行如下命令:

"./node_modules/.bin/electron-rebuild" "./node_modules/ffi"

编译完成后,运行程序,漂亮的界面终于出现了。

四、使用 ffi 调用 Widows API 解决一个小缺陷

上篇文章中的仿 QQ 登录界面还有一个小问题,就是鼠标右键点击窗口的任意地方,都会弹出系统菜单:

现在使用 ffi 调用 user32.dll 中的 GetSystemMenu 函数来解决这个问题,首先新建一个 user32.js 文件,为了展示 ffi ,我多定义了几个API函数:

const ffi = require('ffi')

exports.User32 = ffi.Library('user32', {
'GetWindowLongPtrW': ['int', ['int', 'int']],
'SetWindowLongPtrW': ['int', ['int', 'int', 'long']],
'GetSystemMenu': ['int', ['int', 'bool']],
'DestroyWindow': ['bool', ['int']]
});

修改 app.js 文件,首先导入 user32.js:

const user32 = require('./app/scripts/user32').User32

然后修改如下内容:

win.once('ready-to-show', () => {
let hwnd = win.getNativeWindowHandle() //获取窗口句柄。
user32.GetSystemMenu(hwnd.readUInt32LE(0), true); //禁用系统菜单.
win.show()
})

再运行项目,系统菜单就消失的无影无踪了。

最后,所有代码都已经提交到了github:https://github.com/starts2000/ElectronQQLogin,欢迎获取。

electron 使用 node-ffi 调用 C++ 动态链接库(DLL)的更多相关文章

  1. wincc C脚本如何调用第三方动态链接库dll

    就Wincc本身脚本功能而言并不强大,但是wincc 脚本提供了第三方接口,如通用的Kernel32.dll,User32.dll,Gdi32.dll,大家如果对这些API接口感兴趣,可网上查找关于w ...

  2. JAVA java调用C++动态链接库dll,有详细过程。VS2015+Eclipse以及失败解决方案

    一.新建Java工程,在Java类中声明一个native的方法 新建Java项目 在新建的项目中创建packet(包),并且在包下创建一个Class(类). 接下来,在该类中添加如下代码: ? 1 2 ...

  3. Node.js调用C#代码

    在Node.js的项目中假如我们想去调用已经用C#写的dll库该怎么办呢?在这种情况下Edge.js是一个不错的选择,Edge.js是一款在GitHub上开源的技术,它允许Node.js和.NET c ...

  4. Node调用C++(dll)

    最近开始搞毕设了,打算用自己拿手的js来搞,但是仿佛入坑了,Node还不是很熟.总之,兵来将挡,水来土掩嘛,带着问题学习才是最高效的. 折腾1:Node 调用 C++ 刚开始,虽然我老师把dll文件给 ...

  5. 编译可供C#调用的C/C++动态链接库dll文件

    编译可供C#调用的C/C++动态链接库dll文件,C语言控制台应用程序,探索生成dll过程 由于项目需求,需要公司另一个团队提供相关算法支持,是用C语言编译好的dll库提供给我们进行调用. 但是拿到d ...

  6. VS2010编写动态链接库DLL及单元测试用例,调用DLL测试正确性

    转自:http://blog.csdn.net/testcs_dn/article/details/27237509 本文将创建一个简单的动态链接库,并编写一个控制台应用程序使用该动态链接库,该动态链 ...

  7. ASP.net/C#中如何调用动态链接库DLL

    动态链接库(也称为DLL,即为“Dynamic Link Library”的缩写)是Microsoft Windows最重要的组成要素之一,打开Windows系统文件夹,你会发现文件夹中有很多DLL文 ...

  8. VC++:创建,调用MFC动态链接库(扩展DLL)

    概述 DLL(Dynamic Linkable Library)动态链接库,Dll可以看作一种仓库,仓库中包含了可以直接使用的变量,函数或类. 仓库的发展史经历了"无库" ---& ...

  9. BCB如何编写,调用动态链接库DLL

    一 编写动态链接库DLL DLL简称动态链接库,是Windows中程序的重要组成部分.想象一下,一个程序需要多人共同完成开发,怎么个共同法?这时我们就要考虑把程序分为好几个模块,团队每一个成员开发一个 ...

随机推荐

  1. CentOS开机自动运行自己的脚本详解

    一.root权限编辑/etc/rc.d/rc.local su cd /etc/rc.d/ vi rc.local 二.在这个文件加上你要执行的脚本,全部内容如下: #!/bin/sh # # Thi ...

  2. 2018面向对象程序设计(Java)第18周学习指导及要求

    2018面向对象程序设计(Java) 第18周学习指导及要求(2018.12.27-2018.12.30)   学习目标 (1) 综合掌握java基本程序结构: (2) 综合掌握java面向对象程序设 ...

  3. 二维凸包 Graham扫描算法

    题目链接: http://poj.org/problem?id=1113 求下列点的凸包 求得凸包如下: Graham扫描算法: 找出最左下的点,设为一号点,将其它点对一号点连线,按照与x轴的夹角大小 ...

  4. Django缓存设置

    由于Django构建得是动态网站,每次客户端请求都要严重依赖数据库,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者memcache中, ...

  5. etcd-v2第三集

    简单说下golang的etcd接口例子.etcd api有v2(http+json)和v3(grpc)两个版本,目前大家都用v2,所以... v2: https://github.com/coreos ...

  6. MySQL数据查询之单表查询

    单表查询 简单查询 - 创建表 DROP TABLE IF EXISTS `person`; CREATE TABLE `person` ( `id` ) NOT NULL AUTO_INCREMEN ...

  7. git 忽略文件不起作用

    本人需要提交项目文件,发现总有一些东西不需要提交,然后搜索有”.gitignore”文件可以忽略一些提交,但是发现添加上没有起作用. 要贴的是: /build/ target/ .idea/ *.im ...

  8. NC nc开发工具java虚拟机参数

        -Dnc.exclude.modules=${FIELD_EX_MODULES} -Dnc.runMode=develop -Dnc.server.location=${FIELD_NC_HO ...

  9. 页面仔初窥"前端工程化"

    今天看了几篇前端界的一位大牛--张云龙的文章,其中一篇在自己的理解范围内看得懂一些,有所收获,说的是前端工程化的事,看完算是对前端工程形成了一个模糊的概念. 现在我所接触到的前端开发,还是张云龙大神所 ...

  10. merge and saveorupdate

    首先 saveOrUpdate返回void 也就是什么都不返回 而merge会返回一个对象 merge 在执行session.merge(a)代码后,a对象仍然不是持久化状态,a对象仍然不会被关联到S ...