在Node.js下编写ObjC及汇编函数与JavaScript交

2017-12-01  本文已影响0人  zenny_chen

当前稳定版本的Node.js v8.9.1已经引入了实验性的N-API,我们可以通过这组API来写本地C/C++代码以及与之相兼容的其他编程语言的代码与JavaScript层进行交互。本文将介绍我们如何用自己编写的一套包含Objective-C和汇编语言的本地代码与JavaScript进行交互的。在本文中,我们主要介绍在JavaScript层调用本地代码实现的函数。
在开始之前,我们需要做一些准备工作,包括安装至少版本为8.9.1的Node.js运行时环境,还有node-gyp编译工具,这些可以在这篇博文中找到(看中间段的文字部分)。这篇博文中还包含了如何编译gyp工程的步序,因此这些基本的东西在本文中不详细展开了。下面我们就先列出gyp文件内容:

{
    "targets": [
    {
        "target_name": "test",
        "sources": [ "native.m", "test.s" ]
    }
  ]
}

在上述配置文件中,我们可以看到,这里面的目标模块名为test,源文件有Objective-C语言的native.m,以及汇编语言的test.s。
下面给出最主要的native.m的内容,该源文件列出了暴露给JavaScript端的所有外部函数:

#include <node_api.h>
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#import <Foundation/Foundation.h>

#define var     __auto_type

extern int ASMSub(int a, int b);

static napi_value MyStringMethod(napi_env env, napi_callback_info info) 
{
    napi_value world;
    var str = @"Hello, world!".UTF8String;
    var str_len = strlen(str);
    printf("The length is: %zu\n", str_len);

    napi_create_string_utf8(env, str, str_len, &world);
    
    return world;
}

static napi_value MyIntMethod(napi_env env, napi_callback_info info) 
{
    @autoreleasepool {
        size_t nArgs = 32;
        napi_value inputArgs[32];
        napi_value thisObj;
        
        napi_get_cb_info(env, info, &nArgs, inputArgs, &thisObj, NULL);

        napi_value result;
        
        int32_t argValue = 0;
        napi_get_value_int32(env, inputArgs[0], &argValue);
        
        var array = @[@"abc", @"def", @"xyz"];
        
        napi_create_int32(env, ASMSub(100, argValue) + array.count, &result);
      
        return result;
    }
}


napi_value Init(napi_env env, napi_value exports) 
{
    napi_property_descriptor stringDesc = { "stringMethod", 0, MyStringMethod, 0, 0, 0, napi_default, 0 };
    napi_property_descriptor intDesc = { "intMethod", 0, MyIntMethod, 0, 0, 0, napi_default, 0 };
    napi_define_properties(env, exports, 2, (napi_property_descriptor[]){stringDesc, intDesc});
    
    return exports;
}

NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)

当前,node-gyp编译工具链还不是非常成熟,因此Objective-C中还有不少东西无法使用,比如NSNumber类型就不支持,还有NSLog也不支持,这些对于Clang前端而言都能解析得过,但是后端库没有包含,所以我们用node-gyp命令去构建是没问题的,但在运行时就会发生符号找不到的异常。不过我们用用NSString、NSArray这些还是没有问题的。这个源文件中还引入了一个全局函数——ASMSub,这个函数将在下面的汇编文件中实现。

.text
.align 4
.intel_syntax

.globl _ASMSub


_ASMSub:

    sub edi, esi
    mov eax, edi
    ret

以上三个文件都准备好之后,我们就可以在命令行用cd命令进入到此目录中,然后使用node-gyp configure &&node-gyp build命令进行构建。成功的话最后会显示ok
最后,我们创建一个名为hello.js的JavaScript源文件:

const test = require('./build/Release/test.node');

const str = test.stringMethod();
const value = test.intMethod(30);

console.log("String is: " + str);
console.log("Value is: " + value);

然后我们可以用node hello.js运行来查看结果了。

上一篇下一篇

猜你喜欢

热点阅读