:O it works. Use a sharing policy approach to autocasting pointers.
This commit is contained in:
Родитель
de9a8d6fec
Коммит
7c49e9f886
|
@ -482,8 +482,10 @@ function RegisteredPointer(
|
|||
isReference,
|
||||
isConst,
|
||||
isSmartPointer,
|
||||
sharingPolicy,
|
||||
rawGetPointee,
|
||||
rawConstructor,
|
||||
rawShare,
|
||||
rawDestructor
|
||||
) {
|
||||
this.name = name;
|
||||
|
@ -494,8 +496,10 @@ function RegisteredPointer(
|
|||
this.isReference = isReference;
|
||||
this.isConst = isConst;
|
||||
this.isSmartPointer = isSmartPointer;
|
||||
this.sharingPolicy = sharingPolicy;
|
||||
this.rawGetPointee = rawGetPointee;
|
||||
this.rawConstructor = rawConstructor;
|
||||
this.rawShare = rawShare;
|
||||
this.rawDestructor = rawDestructor;
|
||||
}
|
||||
|
||||
|
@ -511,7 +515,7 @@ RegisteredPointer.prototype.toWireType = function(destructors, handle) {
|
|||
}
|
||||
|
||||
if (this.isSmartPointer) {
|
||||
var ptr = this.rawConstructor(0, 0);
|
||||
var ptr = this.rawConstructor();
|
||||
destructors.push(this.rawDestructor, ptr);
|
||||
return ptr;
|
||||
} else {
|
||||
|
@ -538,14 +542,30 @@ RegisteredPointer.prototype.toWireType = function(destructors, handle) {
|
|||
}
|
||||
var ptr = staticPointerCast(handle.$$.ptr, fromRawType, this.pointeeType.rawType);
|
||||
if (this.isSmartPointer) {
|
||||
// If this is for smart ptr type conversion, I think it
|
||||
// assumes that smart_ptr<T> has an identical binary layout to
|
||||
// smart_ptr<U>. I wonder if that's untrue for any common
|
||||
// smart pointer. - chad
|
||||
ptr = this.rawConstructor(
|
||||
switch (this.sharingPolicy) {
|
||||
case 0: // NONE
|
||||
throwBindingError('NONE sharing policy not yet supported');
|
||||
break;
|
||||
|
||||
case 1: // INTRUSIVE
|
||||
throwBindingError('INTRUSIVE sharing policy not yet supported');
|
||||
break;
|
||||
|
||||
case 2: // BY_EMVAL
|
||||
var clonedHandle = handle.clone();
|
||||
ptr = this.rawShare(
|
||||
ptr,
|
||||
handle.$$.smartPtr);
|
||||
__emval_register(function() {
|
||||
clonedHandle.delete();
|
||||
})
|
||||
);
|
||||
destructors.push(this.rawDestructor, ptr);
|
||||
break;
|
||||
|
||||
default:
|
||||
throwBindingError('Unsupporting sharing policy');
|
||||
|
||||
}
|
||||
}
|
||||
return ptr;
|
||||
};
|
||||
|
@ -932,14 +952,17 @@ function __embind_register_smart_ptr(
|
|||
rawType,
|
||||
rawPointeeType,
|
||||
name,
|
||||
sharingPolicy,
|
||||
rawGetPointee,
|
||||
rawConstructor,
|
||||
rawDestructor,
|
||||
rawGetPointee
|
||||
rawShare,
|
||||
rawDestructor
|
||||
) {
|
||||
name = Pointer_stringify(name);
|
||||
rawConstructor = FUNCTION_TABLE[rawConstructor];
|
||||
rawDestructor = FUNCTION_TABLE[rawDestructor];
|
||||
rawGetPointee = FUNCTION_TABLE[rawGetPointee];
|
||||
rawConstructor = FUNCTION_TABLE[rawConstructor];
|
||||
rawShare = FUNCTION_TABLE[rawShare];
|
||||
rawDestructor = FUNCTION_TABLE[rawDestructor];
|
||||
|
||||
whenDependentTypesAreResolved([rawPointeeType], function(pointeeType) {
|
||||
pointeeType = pointeeType[0];
|
||||
|
@ -1001,8 +1024,10 @@ function __embind_register_smart_ptr(
|
|||
false,
|
||||
false,
|
||||
true,
|
||||
sharingPolicy,
|
||||
rawGetPointee,
|
||||
rawConstructor,
|
||||
rawShare,
|
||||
rawDestructor);
|
||||
registerType(rawType, registeredPointer);
|
||||
pointeeType.smartPointerType = registeredPointer;
|
||||
|
|
|
@ -11,6 +11,12 @@
|
|||
#include <emscripten/wire.h>
|
||||
|
||||
namespace emscripten {
|
||||
enum class sharing_policy {
|
||||
NONE = 0,
|
||||
INTRUSIVE = 1,
|
||||
BY_EMVAL = 2,
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
typedef void (*GenericFunction)();
|
||||
typedef long GenericEnumValue;
|
||||
|
@ -97,9 +103,11 @@ namespace emscripten {
|
|||
TYPEID pointerType,
|
||||
TYPEID pointeeType,
|
||||
const char* pointerName,
|
||||
sharing_policy sharingPolicy,
|
||||
GenericFunction getPointee,
|
||||
GenericFunction constructor,
|
||||
GenericFunction destructor,
|
||||
GenericFunction getPointee);
|
||||
GenericFunction share,
|
||||
GenericFunction destructor);
|
||||
|
||||
void _embind_register_class(
|
||||
TYPEID classType,
|
||||
|
@ -524,38 +532,62 @@ namespace emscripten {
|
|||
// SMART POINTERS
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename PointerType>
|
||||
struct default_smart_ptr_trait {
|
||||
static sharing_policy get_sharing_policy() {
|
||||
return sharing_policy::NONE;
|
||||
}
|
||||
|
||||
static void* share(void* v) {
|
||||
return 0; // no sharing
|
||||
}
|
||||
};
|
||||
|
||||
// specialize if you have a different pointer type
|
||||
template<typename PointerType>
|
||||
struct smart_ptr_trait {
|
||||
struct smart_ptr_trait : public default_smart_ptr_trait<PointerType> {
|
||||
typedef typename PointerType::element_type element_type;
|
||||
|
||||
static element_type* get(const PointerType& ptr) {
|
||||
return ptr.get();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename PointeeType>
|
||||
struct smart_ptr_trait<std::shared_ptr<PointeeType>> {
|
||||
typedef std::shared_ptr<PointeeType> PointerType;
|
||||
typedef typename PointerType::element_type element_type;
|
||||
|
||||
static element_type* get(const PointerType& ptr) {
|
||||
return ptr.get();
|
||||
}
|
||||
|
||||
static PointerType share(const PointerType& r, element_type* ptr) {
|
||||
return PointerType(r, ptr);
|
||||
static sharing_policy get_sharing_policy() {
|
||||
return sharing_policy::BY_EMVAL;
|
||||
}
|
||||
|
||||
static std::shared_ptr<PointeeType>* share(PointeeType* p, internal::EM_VAL v) {
|
||||
return new std::shared_ptr<PointeeType>(
|
||||
p,
|
||||
val_deleter(val::take_ownership(v)));
|
||||
}
|
||||
|
||||
private:
|
||||
class val_deleter {
|
||||
public:
|
||||
val_deleter() = delete;
|
||||
explicit val_deleter(val v)
|
||||
: v(v)
|
||||
{}
|
||||
void operator()(void const*) {
|
||||
v();
|
||||
// eventually we'll need to support emptied out val
|
||||
v = val::undefined();
|
||||
}
|
||||
private:
|
||||
val v;
|
||||
};
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
template<typename SmartPointerType>
|
||||
SmartPointerType* raw_smart_pointer_constructor(
|
||||
typename smart_ptr_trait<SmartPointerType>::element_type* ptr,
|
||||
SmartPointerType* basePtr
|
||||
) {
|
||||
if (ptr) {
|
||||
return new SmartPointerType(smart_ptr_trait<SmartPointerType>::share(*basePtr, ptr));
|
||||
} else {
|
||||
return new SmartPointerType;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename PointerType>
|
||||
typename smart_ptr_trait<PointerType>::element_type* get_pointee(const PointerType& ptr) {
|
||||
return smart_ptr_trait<PointerType>::get(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// CLASSES
|
||||
|
@ -689,17 +721,22 @@ namespace emscripten {
|
|||
template<typename PointerType>
|
||||
class_& smart_ptr() {
|
||||
using namespace internal;
|
||||
typedef typename smart_ptr_trait<PointerType>::element_type PointeeType;
|
||||
|
||||
// TODO: assert that PointeeType is identical to ClassType
|
||||
|
||||
typedef smart_ptr_trait<PointerType> PointerTrait;
|
||||
typedef typename PointerTrait::element_type PointeeType;
|
||||
|
||||
|
||||
_embind_register_smart_ptr(
|
||||
TypeID<PointerType>::get(),
|
||||
TypeID<PointeeType>::get(),
|
||||
"SmartPtr", // TODO: generate unique name
|
||||
reinterpret_cast<GenericFunction>(&raw_smart_pointer_constructor<PointerType>),
|
||||
reinterpret_cast<GenericFunction>(&raw_destructor<PointerType>),
|
||||
reinterpret_cast<GenericFunction>(&get_pointee<PointerType>));
|
||||
"SmartPtr", // TODO: generate unique name, if one is needed at all
|
||||
PointerTrait::get_sharing_policy(),
|
||||
reinterpret_cast<GenericFunction>(&PointerTrait::get),
|
||||
reinterpret_cast<GenericFunction>(&operator_new<PointerType>),
|
||||
reinterpret_cast<GenericFunction>(&PointerTrait::share),
|
||||
reinterpret_cast<GenericFunction>(&raw_destructor<PointerType>));
|
||||
return *this;
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче