[英]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 件事:
**output
參數的類型映射,根本不從 JavaScript 獲取輸入。numinputs=0
是抑制從 JavaScript 被調用者接收參數的需要。tmp$argnum
因為 SWIG 在內部對局部變量進行了編號,以避免在類型映射在 in 類型映射上多次匹配時發生沖突,但它不會在 argout 上自動執行此操作。 SWIG 提供了一些標准宏,用於附加內容以返回多個項目,但它們在這里不起作用,因為它最終會進行非法轉換,而且我不太喜歡使用這些語義。 這里的片段確保我們在生成的代碼中獲得了對可用字符串輸出的一些預先編寫的支持。我之前幾乎從未使用過 SWIG 的 JavaScript 支持,所以一旦我完成了構建模塊的基本文檔,這足以讓我運行以下測試:
var test = require("./build/Release/test");
console.log(test.test("blah blah"));
這按預期工作。 我還做了一個快速測試,更改返回值以強制異常,並且其行為也符合預期。
免責聲明:這樣做幾乎使我接觸 node/V8 的機會增加了一倍,所以請仔細檢查我的工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.