构造一个对象以在其他地方返回值 [英] Constructing an object to return by value elsewhere

查看:140
本文介绍了构造一个对象以在其他地方返回值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在一个包装器中,V8 JavaScript引擎与C ++代码接口,我想调用一个C ++函数按值传递对象。



调用的C ++函数采用类型T的对象,并且模板用于生成适配器函数A,返回T按值。问题是适配器函数A需要调用一个JavaScript函数传递另一个C ++函数B作为回调。类型T的对象在函数B中构造。它不能通过JavaScript返回到A,而JavaScript不知道如何处理类型T的对象。



最简单的方法是在函数A中有一个类型T的局部变量。指向它的一个指针给B,它为局部变量赋值一个新值,A稍后返回,大致如下(有些细节省略了参数传递给callJavaScript和回调,实际上,T的构造函数和B函数可以采用任何更复杂的类型作为参数):



C ++代码: p>

  TA(){
T data;

callJavaScript(someJavaScriptFunction,& B,& 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)> ::类型数据;函数B然后可以使用placement new在该空间中构造对象,但是如何返回结果对象从A使用移动语义?如何正确调用可能的析构函数?



我最后的想法是使用更多的模板欺骗来为函数A中的类型T的构造函数分配参数的空间,通过指针B并最终构造A中的对象,但如果一些参数中的数据超出范围,当callJavaScript返回时,它会令人讨厌。是否有解决方案?



编辑:这一切的目的是获取JavaScript对象的内容到C ++。从C ++读取对象的属性需要使用字符串通过名称查找它们。 V8中的JIT编译函数可以更直接地访问对象的字段,并在someJavaScriptFunction中读取对象的属性,编译为简单的指针读取。然后它可以调用C ++回调与各种参数,这是相当快速的从JavaScript值句柄转换为C ++类型。



EDIT2:简单的第一个想法是:

  typename std :: aligned_storage< sizeof(T),alignof(T)> :: type data; 
:: new(& data)T(); //在另一个函数中实际放置的该行
return(* reinterpret_cast< T *>(& data));

但是我应该为数据中构造的对象T调用析构函数,怎么样?这是一个库,并且向接收方添加代码并不是真正的选择。

解决方案

wrapper around A处理调用placement new和A的析构函数。它允许库的用户提供任何类A,只要它有一个移动构造函数。一个工作测试和讨论的完整代码在一个更新的,更好的拟定问题中找到放置新,按值返回并安全处理临时副本及其接受的答案。


In a wrapper to interface the V8 JavaScript engine with C++ code, I'd like to call a C++ function passing it an object by value. The object is automatically constructed from data inside JavaScript.

The C++ function to call takes an object of type T and a template is used to generate an adapter function A, returning T by value. The problem is that the adapter function A needs to call a JavaScript function passing it another C++ function B as a callback. The object of type T is constructed in that function B. It cannot be returned back to A through JavaScript, which doesn't know how to handle the object of type T.

The simplest way is to have a local variable of type T inside function A. A pointer to it is given to B, which assigns a new value to the local variable, which A later returns, approximately like so (Some details omitted regarding how arguments are passed to callJavaScript and callback. In reality, T's constructor and thus the B function may take any number of more complicated types as parameters):

C++ code:

T A() {
    T data;

    callJavaScript("someJavaScriptFunction", &B, &data);

    return data;
}

void B(T *data, int importantValue) {
    *data = T(importantValue);
}

JavaScript code:

function someJavaScriptFunction(callback, dataRef) {
    callback(dataRef, getImportantValueSomehow());
}

But what if the type T doesn't support assignment or even have a copy constructor? Is there a way to avoid unnecessary copying? I thought of allocating empty space inside function A as a local variable:

typename std::aligned_storage<sizeof(T), alignof(T)>::type data;

Function B could then construct the object in that space using placement new, but how can I return the resulting object from A using move semantics? How to call a possible destructor correctly?

My final idea was to use more template trickery to allocate space for parameters for type T's constructor inside function A, set them through pointers from B and finally construct the object inside A, but it will get nasty if data in some parameters goes out of scope when callJavaScript returns. Is there a solution for that?

EDIT: The point of all this is to get the contents of a JavaScript object into C++. Reading the object's properties from C++ requires looking them up by name using strings. A JIT-compiled function in V8 has more direct access to the object's fields and reads of the object's properties in someJavaScriptFunction get compiled into simple pointer reads. Then it can call the C++ callback with various parameters which are reasonably fast to convert from JavaScript value handles into C++ types.

EDIT2: The simple first idea is:

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));

But should I call the destructor for the object T constructed in data, and when to call it, and how? This is a library and adding code to the recipient of the return value is not really an option.

解决方案

I ended up using a wrapper around A that handles calling placement new and A's destructor. It allows the library's user to supply any class A, as long as it has a move constructor. The full code of a working test and discussion about it are found in a newer, better formulated question Placement new, return by value and safely dispose temporary copies and its accepted answer.

这篇关于构造一个对象以在其他地方返回值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆