构造一个对象在别处按值返回 在V8 JavaScript引擎与C++代码接口的包装器中,我想调用一个C++函数,它通过值传递一个对象。该对象是根据JavaScript中的数据自动构造的 调用C++函数取T类对象,模板用于生成适配器函数A,按值返回T。问题是适配器函数A需要调用JavaScript函数,将它传递给另一个C++函数B作为回调。类型为T的对象是在函数B中构造的。它不能通过JavaScript返回给A,因为JavaScript不知道如何处理类型为T的对象
最简单的方法是在函数a中有一个T类型的局部变量。指向它的指针被赋予B,B给局部变量分配一个新值,a随后返回,大致如此(省略了有关如何将参数传递给callJavaScript和callback的一些细节。实际上,T的构造函数和B函数可能会将任意数量的更复杂类型作为参数): C++代码:构造一个对象在别处按值返回 在V8 JavaScript引擎与C++代码接口的包装器中,我想调用一个C++函数,它通过值传递一个对象。该对象是根据JavaScript中的数据自动构造的 调用C++函数取T类对象,模板用于生成适配器函数A,按值返回T。问题是适配器函数A需要调用JavaScript函数,将它传递给另一个C++函数B作为回调。类型为T的对象是在函数B中构造的。它不能通过JavaScript返回给A,因为JavaScript不知道如何处理类型为T的对象,c++,node.js,c++11,v8,C++,Node.js,C++11,V8,最简单的方法是在函数a中有一个T类型的局部变量。指向它的指针被赋予B,B给局部变量分配一个新值,a随后返回,大致如此(省略了有关如何将参数传递给callJavaScript和callback的一些细节。实际上,T的构造函数和B函数可能会将任意数量的更复杂类型作为参数): C++代码: T A() { T data; callJavaScript("someJavaScriptFunction", &B, &data); return data; }
T A() {
T data;
callJavaScript("someJavaScriptFunction", &B, &data);
return data;
}
void B(T *data, int importantValue) {
*data = T(importantValue);
}
JavaScript代码:
function someJavaScriptFunction(callback, dataRef) {
callback(dataRef, getImportantValueSomehow());
}
但是,如果类型T不支持赋值,甚至没有复制构造函数,该怎么办?有没有办法避免不必要的复制?我想在函数a中分配一个空空间作为局部变量:
typename std::aligned_storage<sizeof(T), alignof(T)>::type data;
typename std::aligned_storage::type data;
然后,函数B可以使用placement new在该空间中构造对象,但是如何使用move语义从A返回结果对象?如何正确调用可能的析构函数
我的最终想法是使用更多的模板技巧为函数A中类型T的构造函数分配参数空间,通过B中的指针进行设置,最后在A中构造对象,但如果调用JavaScript返回时某些参数中的数据超出范围,会变得很糟糕。有解决方案吗
编辑:这一切的要点是把JavaScript对象的内容变成C++。从C++中读取对象的属性需要用字符串来查找它们。然后,它可以调用具有各种参数的C++回调,这些参数相当快,可以将JavaScript值句柄转换成C++类型。
编辑2:第一个简单的想法是:
typename std::aligned_storage<sizeof(T), alignof(T)>::type data;
::new(&data) T(); // THIS LINE ACTUALLY PLACED IN ANOTHER FUNCTION
return(*reinterpret_cast<T *>(&data));
typename std::aligned_storage::type data;
::new(&data)T();//此行实际放在另一个函数中
返回(*重新解释铸件和数据));
但我是否应该为数据中构造的对象T调用析构函数,何时调用,如何调用?这是一个库,向返回值的接收者添加代码并不是一个真正的选项。我不确定我是否完全理解了您的问题,但您似乎不需要在函数中传递输出参数 简单地让函数A返回一个值,正如您在问题中所说的那样,让函数B返回一个值 由于“命名返回值优化”,因此不需要赋值运算符或复制构造函数。也就是说,如果您的代码满足“NRVO”的要求,您就可以:
T B(int importantValue) { return T{importantValue}; }
不需要赋值运算符,也不需要从T复制构造函数。
然后,将callJavascript更改为不需要输出参数,但返回一个值,这样就可以在没有复制构造函数或赋值运算符的情况下工作:
T A() { A rv{callJavascript(&B)}; return rv; }
一般来说,使函数不需要输出参数,否则您需要类型具有复制构造函数和赋值运算符,或者违反类型系统
顺便说一句,使
callJavascript
成为一个以可调用为参数的模板。我不确定我是否完全理解了您的问题,但您似乎不需要在函数中传递输出参数
简单地让函数A返回一个值,正如您在问题中所说的那样,让函数B返回一个值
由于“命名返回值优化”,因此不需要赋值运算符或复制构造函数。也就是说,如果您的代码满足“NRVO”的要求,您就可以:
T B(int importantValue) { return T{importantValue}; }
不需要赋值运算符,也不需要从T复制构造函数。
然后,将callJavascript更改为不需要输出参数,但返回一个值,这样就可以在没有复制构造函数或赋值运算符的情况下工作:
T A() { A rv{callJavascript(&B)}; return rv; }
一般来说,使函数不需要输出参数,否则您需要类型具有复制构造函数和赋值运算符,或者违反类型系统
顺便说一句,让
callJavascript
成为一个以可调用为参数的模板。我最终在a周围使用了一个包装器来处理调用placement new和a的析构函数。它允许库的用户提供任何类a,只要它有一个移动构造函数。关于它出现在一个更新的、更完善的问题及其公认的答案中。我最终在a周围使用了一个包装器来处理调用placement new和a的析构函数。它允许库的用户提供任何类a,只要它有一个移动构造函数。一个工作测试的完整代码和关于它的讨论可以在更新的bette中找到r制定了问题及其公认的答案。问题是B的返回值进入V8 JavaScript引擎,并最终通过someJavaScriptFunction返回给A。暂时将该值包装到可存储在JS变量中的句柄中有点浪费。您能捕获JavaScript返回值吗?如果可以的话B的唯一目的似乎是捕获GetImportantValue
以某种方式产生的整数。如果无法捕获任何任意类型的值,则使用此技术捕获整数的值并从EXPLL调用B