繁体   English   中英

用输出参数包装一个 C++ 函数,以便在 javascript/node 中使用

[英]Wrap a c++ function with output parameter for use in javascript/node

给定一个定义为int test(char* input, char** output);的函数 . 如何配置 SWIG 接口以便获得输出值?

这是我从 js 调用它的方式:

var input = 'input1';
var output = '';
var result = mylib.test(input, output);
console.log(output);

我知道这不起作用,因为字符串在 javascript 中是不可变的,而且在 SWIG 中创建的接口不会写回输出参数。

这是C++代码:

int test(char* input, char** output) {
  *output = input;
  return 0;
}

将您展示的 C++ 语义映射到 JavaScript 的最简单方法是使 SWIG 使函数的行为与您使用真正的 JavaScript 而不是 C++ 编写的一样。 也就是说,我们将使您的函数的行为类似于以下 JavaScript 伪代码:

function test(input) {
    if (error) {
        throw ....
    }
    return input;
}

要使用 SWIG 做到这一点,我们需要编写一些类型映射。 (在某些情况下,这些类型映射已经作为标准 SWIG 库的一部分存在,但对于char **没有这样的类型映射,因为语义不太明显)。

我使您的代码与以下 SWIG 接口一起工作,注释如下:

%module test

// #1
%typemap(in,numinputs=0) char **output (char *tmp) {
    $1 = &tmp; // #2
}

// #3
%typemap(argout,fragment="SWIG_FromCharPtr") char **output {
    $result = SWIG_FromCharPtr(tmp$argnum);
    // Without more effort the following would be an illegal cast I think:
    //SWIG_AppendOutput($result, tmp$argnum);
}

// #4
%typemap(out) int test %{
    if ($1) {
        SWIG_exception_fail(SWIG_ERROR, "Well, that was unexpected");
    }
%}

%inline %{
int test(char *input, char **output) {
    *output = input;
    return 0;
}
%}

基本上我们在这里做了 4 件事:

  1. 设置**output参数的类型映射,根本不从 JavaScript 获取输入。numinputs=0是抑制从 JavaScript 被调用者接收参数的需要。
  2. 相反,我们使用局部变量作为纯粹在包装器内部的输出
  3. 在函数被调用后,使用我们本地变量中的值作为函数返回给 JavaScript。 我们需要将它称为tmp$argnum因为 SWIG 在内部对局部变量进行了编号,以避免在类型映射在 in 类型映射上多次匹配时发生冲突,但它不会在 argout 上自动执行此操作。 SWIG 提供了一些标准宏,用于附加内容以返回多个项目,但它们在这里不起作用,因为它最终会进行非法转换,而且我不太喜欢使用这些语义。 这里的片段确保我们在生成的代码中获得了对可用字符串输出的一些预先编写的支持。
  4. 对原始返回值做一些事情,在这种情况下,如果我们从 C++ 得到非零(即错误),则会抛出异常。 还有其他方法可以处理这个问题,但这是最简单的方法,而不是默默地忽略错误。

我之前几乎从未使用过 SWIG 的 JavaScript 支持,所以一旦我完成了构建模块基本文档,这足以让我运行以下测试:

var test = require("./build/Release/test");

console.log(test.test("blah blah"));

这按预期工作。 我还做了一个快速测试,更改返回值以强制异常,并且其行为也符合预期。

免责声明:这样做几乎使我接触 node/V8 的机会增加了一倍,所以请仔细检查我的工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM