Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 31 additions & 23 deletions classwrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,26 +77,36 @@ namespace upywrap
ClassWrapper( const char* name, mp_obj_dict_t* dict, decltype( mp_obj_type_t::flags ) flags = 0 ) :
ClassWrapper( name, flags )
{
mp_obj_dict_store( dict, new_qstr( name ), &type );
mp_obj_dict_store( dict, new_qstr( ( std::string( name ) + "_locals" ).data() ), MP_OBJ_FROM_PTR( MP_OBJ_TYPE_GET_SLOT( &type, locals_dict ) ) );
mp_obj_dict_store( dict, new_qstr( name ), FullTypePtr() );
mp_obj_dict_store( dict, new_qstr( ( std::string( name ) + "_locals" ).data() ), MP_OBJ_FROM_PTR( MP_OBJ_TYPE_GET_SLOT( FullTypePtr(), locals_dict ) ) );
}

//Initialize the type, storing the locals in StaticPyObjectStore to prevent GC collection.
ClassWrapper( const char* name, ConstructorOptions, decltype( mp_obj_type_t::flags ) flags = 0 ) :
ClassWrapper( name, flags )
{
StaticPyObjectStore::Store( MP_OBJ_FROM_PTR( MP_OBJ_TYPE_GET_SLOT( &type, locals_dict ) ) );
StaticPyObjectStore::Store( MP_OBJ_FROM_PTR( MP_OBJ_TYPE_GET_SLOT( FullTypePtr(), locals_dict ) ) );
}

static mp_obj_full_type_t* FullTypePtr()
{
return type_ptr;
}

static const mp_obj_full_type_t& FullType()
{
return *FullTypePtr();
}

static const mp_obj_type_t& Type()
{
return *((const mp_obj_type_t*) &type);
return (const mp_obj_type_t&) FullType();
}

template< class A >
void StoreClassVariable( const char* name, const A& value )
{
mp_obj_dict_store( MP_OBJ_FROM_PTR( MP_OBJ_TYPE_GET_SLOT( &type, locals_dict ) ), new_qstr( name ), ToPy( value ) );
mp_obj_dict_store( MP_OBJ_FROM_PTR( MP_OBJ_TYPE_GET_SLOT( FullTypePtr(), locals_dict ) ), new_qstr( name ), ToPy( value ) );
}

template< index_type name, class Ret, class... A >
Expand Down Expand Up @@ -313,7 +323,7 @@ namespace upywrap
assert( p );
CheckTypeIsRegistered();
auto o = (this_type*) m_malloc_with_finaliser( sizeof( this_type ) );
o->base.type = (const mp_obj_type_t*) & type;
o->base.type = (const mp_obj_type_t*) &Type();
o->cookie = defCookie;
#if UPYWRAP_FULLTYPECHECK
o->typeId = &typeid( T );
Expand All @@ -329,7 +339,7 @@ namespace upywrap
static ClassWrapper< T >* AsNativeObjCheckedImpl( mp_obj_t arg )
{
auto native = (this_type*) MP_OBJ_TO_PTR( arg );
if( !mp_obj_is_exact_type( arg, (const mp_obj_type_t*) &type ) )
if( !mp_obj_is_exact_type( arg, (const mp_obj_type_t*) &Type() ) )
{
//If whatever gets passed in doesn't remotely look like an object bail out.
//Otherwise it's possible we're being passed an arbitrary 'opaque' ClassWrapper (so the cookie mathches)
Expand Down Expand Up @@ -389,7 +399,7 @@ namespace upywrap
}
}
CheckTypeIsRegistered(); //since we want to access type.name
RaiseTypeException( arg, qstr_str( type.name ) );
RaiseTypeException( arg, qstr_str( FullType().name ) );
#if !defined( _MSC_VER ) || defined( _DEBUG )
return nullptr;
#endif
Expand Down Expand Up @@ -430,10 +440,10 @@ namespace upywrap
if( !init )
{
OneTimeInit( name );
type.flags = flags;
FullTypePtr()->flags = flags;
init = true;
}
else if( type.flags != flags )
else if( FullType().flags != flags )
{
RaiseTypeException( "ClassWrapper's type flags can only be set once" );
}
Expand Down Expand Up @@ -502,14 +512,14 @@ namespace upywrap
const auto attrValue = FindAttrMaybe( map, attr );
if( !attrValue )
{
RaiseAttributeException( type.name, attr );
RaiseAttributeException( FullType().name, attr );
}
return attrValue;
}

static mp_map_elem_t* LookupLocal( qstr attr )
{
auto locals_map = &( (mp_obj_dict_t*) MP_OBJ_TYPE_GET_SLOT( &type, locals_dict ) )->map;
auto locals_map = &( (mp_obj_dict_t*) MP_OBJ_TYPE_GET_SLOT( FullTypePtr(), locals_dict ) )->map;
return mp_map_lookup( locals_map, new_qstr( attr ), MP_MAP_LOOKUP );
}

Expand Down Expand Up @@ -619,6 +629,9 @@ namespace upywrap

void OneTimeInit( const char* name )
{
type_ptr = new mp_obj_full_type_t({});
mp_obj_full_type_t& type = *FullTypePtr();

type.base.type = &mp_type_type;
type.name = static_cast< decltype( type.name ) >( qstr_from_str( name ) );
//The ones we use here (so make sure the other locations stay in sync!).
Expand All @@ -644,7 +657,7 @@ namespace upywrap

static void CheckTypeIsRegistered()
{
if( type.base.type == nullptr )
if( FullType().base.type == nullptr )
{
#if UPYWRAP_HAS_TYPEID
std::string errorMessage( std::string( "Native type " ) + typeid( T ).name() + " has not been registered" );
Expand All @@ -657,7 +670,7 @@ namespace upywrap

void AddFunctionToTable( const qstr name, mp_obj_t fun )
{
mp_obj_dict_store( MP_OBJ_TYPE_GET_SLOT( &type, locals_dict ), new_qstr( name ), fun );
mp_obj_dict_store( MP_OBJ_TYPE_GET_SLOT( FullTypePtr(), locals_dict ), new_qstr( name ), fun );
}

void AddFunctionToTable( const char* name, mp_obj_t fun )
Expand All @@ -676,7 +689,7 @@ namespace upywrap
AddFunctionToTable( name(), call_type::CreateUPyFunction( *callerObject ) );
if( std::string( name() ) == "__call__" )
{
MP_OBJ_TYPE_SET_SLOT( &type, call, instance_call, 5 );
MP_OBJ_TYPE_SET_SLOT( FullTypePtr(), call, instance_call, 5 );
}
}

Expand Down Expand Up @@ -705,7 +718,7 @@ namespace upywrap
auto caller = call_type::CreateCaller( f );
caller->arguments = std::move( arguments );
functionPointers[ (void*) name ] = caller;
MP_OBJ_TYPE_SET_SLOT( &type, make_new, call_type::MakeNew, 0 );
MP_OBJ_TYPE_SET_SLOT( FullTypePtr(), make_new, call_type::MakeNew, 0 );
}

template< index_type name, class Fun, class Ret, class... A >
Expand Down Expand Up @@ -921,20 +934,15 @@ namespace upywrap
std::int64_t cookie; //we'll use this to check if a pointer really points to a ClassWrapper
const std::type_info* typeId; //and this will be used to check if types aren't being mixed
native_obj_t obj;
static mp_obj_full_type_t type;
static mp_obj_full_type_t* type_ptr;
static function_ptrs functionPointers;
static store_attr_map setters;
static load_attr_map getters;
static const std::int64_t defCookie;
};

template< class T >
mp_obj_full_type_t ClassWrapper< T >::type =
#ifdef __GNUC__
{ { nullptr } }; //GCC bug 53119
#else
{ nullptr };
#endif
mp_obj_full_type_t* ClassWrapper< T >::type_ptr = nullptr;

template< class T >
function_ptrs ClassWrapper< T >::functionPointers;
Expand Down