构建在xp(sp3)系统上nw.js能正常使用的node-ffi模块

安装基础配置

安装nvm

nvm下载node版本5.12.0 32并且切换到该版本。

如果你只用5.12.0版本开发,那么可以跳过这一步。如果安装失败,可以在网上搜索相关资料。(一般都是卸载干净node版本后再进行安装,包括node的缓存目录等等)

nw.js在xp系统上最新的LTS版本为0.14.7,对应能支持最高的node版本为5.x。而最新的5.xnode版本为5.12.0。
为了支持在32位系统中也能正常使用,所以建议安装32版本。
对应命令为:

nvm install 5.12.0 32

安装完成后记得切换版本

nvm use 5.12.0 32

5.x版本带来的影响

低版本的node不支持ES6语法,所以直接安装最新的库,很多都会运行不起来。所以后面安装的库都会指定版本,否则会安装失败!

安装nrm

为了提高安装速度,国内用户建议使用nrm管理npm registry
安装命令

npm install -g nrm@1.0.1

安装完成之后,切换仓库源

nrm use cnpm

安装node-gyp

node-gyp是用于编译node-ffi模块必需的库。
安装命令

npm install -g node-gyp@3.4.0

node-gyp可能还有各种编译配置,具体大家需要去查看官网配置教程。

安装npm

由于低版本npm构建与高版本npm构建并不一样,所以如果你不安装低版本的npm很可能会构建失败,
比如说你直接安装node-ffi,可能就会报错:

E:\xxx\node_modules\ffi>if not defined npm_config_node_gyp (node "C:\xxx\nvm\v5.12.0\node_modules\npm\bin\node-gyp-bin\\..\..\node_modules\node-gyp\bin\node-gyp.js" rebuild )  else (node "" rebuild )
在此解决方案中一次生成一个项目。若要启用并行生成,请添加“/m”开关。
  Building assembly file ..\..\..\deps\libffi\src\x86\win32.asm
   Assembling: ..\..\..\deps\libffi\src\x86\win32.asm
  prep_cif.c
  types.c
  raw_api.c
  java_raw_api.c
  closures.c
  ffi.c
  win_delay_load_hook.c
C:\xxx\nvm\v5.12.0\node_modules\npm\node_modules\node-gyp\src\win_delay_load_hook.c(34): error
C2373: “__pfnDliNotifyHook2”: 重定义;不同的类型修饰符 [E:\xxx\node_m
odules\ffi\build\deps\libffi\ffi.vcxproj]

这里推荐安装3.10.10版本的npm
安装命令:

npm install -g npm@3.10.10

安装成功之后,可以项目目录中安装node-ffi进行测试,正常情况会安装成功,这说明你的基础库和配置都已经正确了,不过还没结束哦。


适配XP系统

修改ffi源码

文件路径:

E:\xxx\node_modules\ffi\src\win32-dlfcn.cc

源文件内容:

/**
 * @file Minimal emulation of POSIX dlopen/dlsym/dlclose on Windows.
 * @license Public domain.
 *
 * This code works fine for the common scenario of loading a
 * specific DLL and calling one (or more) functions within it.
 *
 * No attempt is made to emulate POSIX symbol table semantics.
 * The way Windows thinks about dynamic linking is fundamentally
 * different, and there's no way to emulate the useful aspects of
 * POSIX semantics.
 */

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <windows.h>
#include <stdio.h>
#include <malloc.h>

#include "win32-dlfcn.h"

/**
 * Win32 error code from last failure.
 */

static DWORD lastError = 0;

#ifdef __cplusplus
extern "C" {
#endif

/**
 * Convert UTF-8 string to Windows UNICODE (UCS-2 LE).
 *
 * Caller must free() the returned string.
 */

static
WCHAR*
UTF8toWCHAR(
    const char* inputString /** UTF-8 string. */
)
{
    int outputSize;
    WCHAR* outputString;

    outputSize = MultiByteToWideChar(CP_UTF8, 0, inputString, -1, NULL, 0);

    if (outputSize == 0)
        return NULL;

    outputString = (WCHAR*) malloc(outputSize * sizeof(WCHAR));

    if (outputString == NULL) {
        SetLastError(ERROR_OUTOFMEMORY);
        return NULL;
    }

    if (MultiByteToWideChar(CP_UTF8, 0, inputString, -1, outputString, outputSize) != outputSize)
    {
        free(outputString);
        return NULL;
    }

    return outputString;
}

/**
 * Open DLL, returning a handle.
 */

void*
dlopen(
    const char* file,   /** DLL filename (UTF-8). */
    int mode            /** mode flags (ignored). */
)
{
    WCHAR* unicodeFilename;
    UINT errorMode;
    void* handle;

    UNREFERENCED_PARAMETER(mode);

    if (file == NULL)
        return (void*) GetModuleHandle(NULL);

    unicodeFilename = UTF8toWCHAR(file);

    if (unicodeFilename == NULL) {
        lastError = GetLastError();
        return NULL;
    }

    errorMode = GetErrorMode();//这里!这里!这里!这里!这里!这里!这一行注释掉

    /* Have LoadLibrary return NULL on failure; prevent GUI error message. */
    SetErrorMode(errorMode | SEM_FAILCRITICALERRORS);//这里!这里!这里!这里!这一行注释掉

    handle = (void*) LoadLibraryW(unicodeFilename);

    if (handle == NULL)
        lastError = GetLastError();

    SetErrorMode(errorMode);

    free(unicodeFilename);

    return handle;
}

/**
 * Close DLL.
 */

int
dlclose(
    void* handle        /** Handle from dlopen(). */
)
{
    int rc = 0;

    if (handle != (void*) GetModuleHandle(NULL))
        rc = !FreeLibrary((HMODULE) handle);

    if (rc)
        lastError = GetLastError();

    return rc;
}

/**
 * Look up symbol exported by DLL.
 */

void*
dlsym(
    void* handle,       /** Handle from dlopen(). */
    const char* name    /** Name of exported symbol (ASCII). */
)
{
    void* address = (void*) GetProcAddress((HMODULE) handle, name);

    if (address == NULL)
        lastError = GetLastError();

    return address;
}

/**
 * Return message describing last error.
 */

char*
dlerror(void)
{
    static char errorMessage[64];

    if (lastError != 0) {
        sprintf(errorMessage, "Win32 error %lu", lastError);
        lastError = 0;
        return errorMessage;
    } else {
        return NULL;
    }
}

#ifdef __cplusplus
}
#endif

进行注释掉之后,记得保存。

 //errorMode = GetErrorMode();
 // SetErrorMode(errorMode | SEM_FAILCRITICALERRORS);

替换node-gyp文件

在windows系统中还需要一个操作,就是将全局中node-gyp的
<npm-path>\node_modules\node-gyp\src\win_delay_load_hook.cc文件,
替换成https://github.com/nwjs/nw.js/blob/nw18/tools/win_delay_load_hook.cc 的文件。
在这里插入图片描述

推荐直接打开https://github.com/nwjs/nw.js/blob/nw18/tools/win_delay_load_hook.cc 地址,然后点击raw,将内容直接复制到node-gyp的win_delay_load_hook.c文件中

注意

  • nw18中的文件,不是nw13。(有个中文文档上写的就是nw13)
  • 确认修改的路径。不是npm>node_modules中node-gyp。而是与npm同级别的node-gyp
    在这里插入图片描述

重新编译ffi

进入到ffi目录下,输入命令

node-gyp rebuild

编译成功:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值