diff --git a/classwrapper.h b/classwrapper.h index d341c7f..a236eb8 100644 --- a/classwrapper.h +++ b/classwrapper.h @@ -78,7 +78,7 @@ namespace upywrap 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_from_concat_str( name, "_locals" ), MP_OBJ_FROM_PTR( MP_OBJ_TYPE_GET_SLOT( &type, locals_dict ) ) ); } //Initialize the type, storing the locals in StaticPyObjectStore to prevent GC collection. @@ -647,11 +647,10 @@ namespace upywrap if( type.base.type == nullptr ) { #if UPYWRAP_HAS_TYPEID - std::string errorMessage( std::string( "Native type " ) + typeid( T ).name() + " has not been registered" ); + RaiseTypeExceptionFmt( "Native type %s has not been registered", typeid( T ).name() ); #else - std::string errorMessage( "Native type has not been registered" ); + RaiseTypeException( "Native type has not been registered" ); #endif - RaiseTypeException( errorMessage.c_str() ); } } @@ -674,7 +673,7 @@ namespace upywrap callerObject->arguments = std::move( arguments ); functionPointers[ (void*) name ] = callerObject; AddFunctionToTable( name(), call_type::CreateUPyFunction( *callerObject ) ); - if( std::string( name() ) == "__call__" ) + if( std::string_view( name() ) == "__call__" ) { MP_OBJ_TYPE_SET_SLOT( &type, call, instance_call, 5 ); } @@ -824,7 +823,7 @@ namespace upywrap { if( caller.arguments.NumberOfArguments() != sizeof...( A ) ) { - RaiseTypeException( ( std::string( "Wrong number of arguments in definition of " ) + index() ).data() ); + RaiseTypeExceptionFmt( "Wrong number of arguments in definition of %s", index() ); } return MakeFunction( caller.arguments.MimimumNumberOfArguments(), CallKw ); } @@ -847,7 +846,7 @@ namespace upywrap { if( f->arguments.NumberOfArguments() != sizeof...( A ) ) { - RaiseTypeException( ( std::string( "Wrong number of arguments in definition of " ) + index() ).data() ); + RaiseTypeExceptionFmt( "Wrong number of arguments in definition of %s", index() ); } Arguments::parsed_obj_t parsedArgs{}; f->arguments.Parse( n_args, n_kw, args, parsedArgs ); @@ -857,7 +856,7 @@ namespace upywrap } else if( n_args != sizeof...( A ) || n_kw ) { - RaiseTypeException( ( std::string( "Wrong number of arguments in definition of " ) + index() ).data() ); + RaiseTypeExceptionFmt( "Wrong number of arguments in definition of %s", index() ); } UPYWRAP_TRY return AsPyObj( native_obj_t( Apply( f, args, make_index_sequence< sizeof...( A ) >() ) ) ); diff --git a/detail/micropython.h b/detail/micropython.h index 73f87f4..3a9f70b 100644 --- a/detail/micropython.h +++ b/detail/micropython.h @@ -3,6 +3,7 @@ #include "micropythonc.h" #include +#include #include #include #include @@ -21,6 +22,17 @@ namespace upywrap return new_qstr( qstr_from_str( what ) ); } + inline mp_obj_t new_qstr_from_concat_str( const char* str1, const char* str2 ) + { + vstr_t concat_str {}; + vstr_init_len( &concat_str, strlen( str1 ) + strlen( str2 ) ); + vstr_add_str( &concat_str, str1 ); + vstr_add_str( &concat_str, str2 ); + mp_obj_t concat_qstr = new_qstr(qstr_from_str( concat_str.buf )); + vstr_clear( &concat_str ); + return concat_qstr; + } + inline mp_obj_t MakeFunction( mp_obj_t (*fun) ( void ) ) { auto o = mp_obj_malloc( mp_obj_fun_builtin_fixed_t, &mp_type_fun_builtin_0 ); @@ -110,15 +122,17 @@ namespace upywrap * Use in place of mp_obj_new_exception_msg if the message string needs to be copied * (mp_obj_new_exception_msg assumes the message passed to it is in ROM so just stores the char pointer) */ - inline mp_obj_t RaiseException( const mp_obj_type_t* exc_type, const char* msg ) + inline mp_obj_t RaiseException( const mp_obj_type_t* exc_type, const char* fmt, ... ) { - mp_obj_exception_t* o = mp_obj_malloc_var( mp_obj_exception_t, args, mp_obj_tuple_t, 0, exc_type ); - o->traceback_data = nullptr; - o->args = reinterpret_cast< mp_obj_tuple_t* >( MP_OBJ_TO_PTR( mp_obj_new_tuple( 1, nullptr ) ) ); - o->args->items[ 0 ] = mp_obj_new_str( msg, std::strlen( msg ) ); - nlr_raise( MP_OBJ_FROM_PTR( o ) ); + va_list args; + va_start(args, fmt); + mp_obj_t exc = mp_obj_new_exception_msg_varg(exc_type, MP_ERROR_TEXT ( fmt ), args); + va_end(args); + nlr_raise( exc ); } +#define RaiseTypeExceptionFmt( msg, ... ) RaiseException( &mp_type_TypeError, msg, ##__VA_ARGS__ ) + inline void RaiseTypeException( const char* msg ) { RaiseException( &mp_type_TypeError, msg ); diff --git a/detail/micropythonc.h b/detail/micropythonc.h index c04347b..4bade63 100644 --- a/detail/micropythonc.h +++ b/detail/micropythonc.h @@ -22,4 +22,4 @@ extern "C" #pragma warning ( default : 4200 ) #endif -#endif //#ifndef MICROPYTHON_WRAP_DETAIL_MICROPYTHONC_H +#endif //#ifndef MICROPYTHON_WRAP_DETAIL_MICROPYTHONC_H \ No newline at end of file diff --git a/functionwrapper.h b/functionwrapper.h index aef79d1..7dbe5ac 100644 --- a/functionwrapper.h +++ b/functionwrapper.h @@ -80,7 +80,7 @@ namespace upywrap { if( caller.arguments.NumberOfArguments() != sizeof...( A ) ) { - RaiseTypeException( ( std::string( "Wrong number of arguments in definition of " ) + index() ).data() ); + RaiseTypeExceptionFmt( "Wrong number of arguments in definition of %s", index() ); } return MakeFunction( caller.arguments.MimimumNumberOfArguments(), CallKw ); }