diff options
author | Matthew J. Francis <mjay.francis@gmail.com> | 2015-07-23 11:36:38 +0800 |
---|---|---|
committer | Matthew Francis <mjay.francis@gmail.com> | 2015-07-27 07:40:34 +0000 |
commit | 9c5a217681935d661aad4d5667a775319382d22a (patch) | |
tree | 29c94ae9316f3a8899ffa8a7ecaf6123e15748b4 /pyuno | |
parent | loplugin:cstylecast (diff) | |
download | core-9c5a217681935d661aad4d5667a775319382d22a.tar.gz core-9c5a217681935d661aad4d5667a775319382d22a.zip |
Tweak introspection/invocation to be more useful to PyUNO
- Make introspection/invocation handle XNameReplace and
XIndexReplace
- Make introspection handle XUnoTunnel
- Adapt PyUNO to take advantage of the additionally handled
interfaces
Change-Id: Ie848d10fd2c31cad76fcc3a746262a490a2c9ae1
Reviewed-on: https://gerrit.libreoffice.org/17314
Reviewed-by: Matthew Francis <mjay.francis@gmail.com>
Tested-by: Matthew Francis <mjay.francis@gmail.com>
Diffstat (limited to 'pyuno')
-rw-r--r-- | pyuno/source/module/pyuno.cxx | 95 | ||||
-rw-r--r-- | pyuno/source/module/pyuno_adapter.cxx | 27 | ||||
-rw-r--r-- | pyuno/source/module/pyuno_impl.hxx | 9 | ||||
-rw-r--r-- | pyuno/source/module/pyuno_module.cxx | 4 | ||||
-rw-r--r-- | pyuno/source/module/pyuno_runtime.cxx | 22 |
5 files changed, 82 insertions, 75 deletions
diff --git a/pyuno/source/module/pyuno.cxx b/pyuno/source/module/pyuno.cxx index f068961fb9aa..ccab344b5b44 100644 --- a/pyuno/source/module/pyuno.cxx +++ b/pyuno/source/module/pyuno.cxx @@ -60,6 +60,7 @@ using com::sun::star::uno::XComponentContext; using com::sun::star::lang::XSingleServiceFactory; using com::sun::star::lang::XServiceInfo; using com::sun::star::lang::XTypeProvider; +using com::sun::star::lang::XUnoTunnel; using com::sun::star::script::XTypeConverter; using com::sun::star::script::XInvocation2; using com::sun::star::beans::XMaterialHolder; @@ -563,7 +564,7 @@ sal_Int32 lcl_detach_getLength( PyUNO *me ) // returned by getElementNames(), or the user may be surprised. // For XIndexContainer - Reference< XIndexAccess > xIndexAccess( me->members->wrappedObject, UNO_QUERY ); + Reference< XIndexAccess > xIndexAccess( me->members->xInvocation, UNO_QUERY ); if ( xIndexAccess.is() ) { return xIndexAccess->getCount(); @@ -571,7 +572,7 @@ sal_Int32 lcl_detach_getLength( PyUNO *me ) // For XNameContainer // Not terribly efficient - get the count of all the names - Reference< XNameAccess > xNameAccess( me->members->wrappedObject, UNO_QUERY ); + Reference< XNameAccess > xNameAccess( me->members->xInvocation, UNO_QUERY ); if ( xNameAccess.is() ) { return xNameAccess->getElementNames().getLength(); @@ -782,7 +783,7 @@ PyObject* lcl_getitem_index( PyUNO *me, PyObject *pKey, Runtime& runtime ) { PyThreadDetach antiguard; - Reference< XIndexAccess > xIndexAccess( me->members->wrappedObject, UNO_QUERY ); + Reference< XIndexAccess > xIndexAccess( me->members->xInvocation, UNO_QUERY ); if ( xIndexAccess.is() ) { if (nIndex < 0) @@ -809,7 +810,7 @@ PyObject* lcl_getitem_slice( PyUNO *me, PyObject *pKey ) { PyThreadDetach antiguard; - xIndexAccess.set( me->members->wrappedObject, UNO_QUERY ); + xIndexAccess.set( me->members->xInvocation, UNO_QUERY ); if ( xIndexAccess.is() ) nLen = xIndexAccess->getCount(); } @@ -850,7 +851,7 @@ PyObject* lcl_getitem_string( PyUNO *me, PyObject *pKey, Runtime& runtime ) { PyThreadDetach antiguard; - Reference< XNameAccess > xNameAccess( me->members->wrappedObject, UNO_QUERY ); + Reference< XNameAccess > xNameAccess( me->members->xInvocation, UNO_QUERY ); if ( xNameAccess.is() ) { aRet = xNameAccess->getByName( sKey ); @@ -914,8 +915,8 @@ PyObject* PyUNO_getitem( PyObject *self, PyObject *pKey ) // If the object is an XIndexAccess and/or XNameAccess, but the // key passed wasn't suitable, give a TypeError which specifically // describes this - Reference< XIndexAccess > xIndexAccess( me->members->wrappedObject, UNO_QUERY ); - Reference< XNameAccess > xNameAccess( me->members->wrappedObject, UNO_QUERY ); + Reference< XIndexAccess > xIndexAccess( me->members->xInvocation, UNO_QUERY ); + Reference< XNameAccess > xNameAccess( me->members->xInvocation, UNO_QUERY ); if ( xIndexAccess.is() || xNameAccess.is() ) { PyErr_SetString( PyExc_TypeError, "subscription with invalid type" ); @@ -985,11 +986,11 @@ int lcl_setitem_index( PyUNO *me, PyObject *pKey, PyObject *pValue ) { PyThreadDetach antiguard; - xIndexContainer.set( me->members->wrappedObject, UNO_QUERY ); + xIndexContainer.set( me->members->xInvocation, UNO_QUERY ); if ( xIndexContainer.is() ) xIndexReplace.set( xIndexContainer, UNO_QUERY ); else - xIndexReplace.set( me->members->wrappedObject, UNO_QUERY ); + xIndexReplace.set( me->members->xInvocation, UNO_QUERY ); if ( xIndexReplace.is() && nIndex < 0 ) nIndex += xIndexReplace->getCount(); @@ -1032,11 +1033,11 @@ int lcl_setitem_slice( PyUNO *me, PyObject *pKey, PyObject *pValue ) { PyThreadDetach antiguard; - xIndexContainer.set( me->members->wrappedObject, UNO_QUERY ); + xIndexContainer.set( me->members->xInvocation, UNO_QUERY ); if ( xIndexContainer.is() ) xIndexReplace.set( xIndexContainer, UNO_QUERY ); else - xIndexReplace.set( me->members->wrappedObject, UNO_QUERY ); + xIndexReplace.set( me->members->xInvocation, UNO_QUERY ); if ( xIndexReplace.is() ) nLen = xIndexReplace->getCount(); @@ -1165,12 +1166,12 @@ int lcl_setitem_string( PyUNO *me, PyObject *pKey, PyObject *pValue ) { PyThreadDetach antiguard; - Reference< XNameContainer > xNameContainer( me->members->wrappedObject, UNO_QUERY ); + Reference< XNameContainer > xNameContainer( me->members->xInvocation, UNO_QUERY ); Reference< XNameReplace > xNameReplace; if ( xNameContainer.is() ) xNameReplace.set( xNameContainer, UNO_QUERY ); else - xNameReplace.set( me->members->wrappedObject, UNO_QUERY ); + xNameReplace.set( me->members->xInvocation, UNO_QUERY ); if ( xNameReplace.is() ) { @@ -1277,17 +1278,17 @@ PyObject* PyUNO_iter( PyObject *self ) { PyThreadDetach antiguard; - xEnumerationAccess.set( me->members->wrappedObject, UNO_QUERY ); + xEnumerationAccess.set( me->members->xInvocation, UNO_QUERY ); if ( xEnumerationAccess.is() ) xEnumeration = xEnumerationAccess->createEnumeration(); else xEnumeration.set( me->members->wrappedObject, UNO_QUERY ); if ( !xEnumeration.is() ) - xIndexAccess.set( me->members->wrappedObject, UNO_QUERY ); + xIndexAccess.set( me->members->xInvocation, UNO_QUERY ); if ( !xIndexAccess.is() ) - xNameAccess.set( me->members->wrappedObject, UNO_QUERY ); + xNameAccess.set( me->members->xInvocation, UNO_QUERY ); } // XEnumerationAccess iterator @@ -1373,7 +1374,7 @@ int PyUNO_contains( PyObject *self, PyObject *pKey ) { PyThreadDetach antiguard; - xNameAccess.set( me->members->wrappedObject, UNO_QUERY ); + xNameAccess.set( me->members->xInvocation, UNO_QUERY ); if ( xNameAccess.is() ) { bool hasKey = xNameAccess->hasByName( sKey ); @@ -1765,51 +1766,43 @@ PyRef getPyUnoClass() return PyRef( reinterpret_cast< PyObject * > ( &PyUNOType ) ); } -PyObject* PyUNO_new ( - const Any & targetInterface, const Reference<XSingleServiceFactory> &ssf) -{ - Reference<XInterface> tmp_interface; - - targetInterface >>= tmp_interface; - - if (!tmp_interface.is ()) - { - // empty reference ! - Py_INCREF( Py_None ); - return Py_None; - } - return PyUNO_new_UNCHECKED (targetInterface, ssf); -} - - -PyObject* PyUNO_new_UNCHECKED ( +PyRef PyUNO_new ( const Any &targetInterface, - const Reference<XSingleServiceFactory> &ssf ) + const Reference<XSingleServiceFactory> &ssf, + const bool bCheckExisting ) { - Reference<XInterface> tmp_interface; - Reference<XInvocation2> tmp_invocation; + Reference<XInvocation2> xInvocation; + { PyThreadDetach antiguard; - Sequence<Any> arguments(1); - arguments[0] <<= targetInterface; - tmp_interface = ssf->createInstanceWithArguments(arguments); - tmp_invocation.set(tmp_interface, UNO_QUERY); - if (!tmp_invocation.is() && tmp_interface.is()) { + xInvocation.set( + ssf->createInstanceWithArguments( Sequence<Any>( &targetInterface, 1 ) ), UNO_QUERY ); + if( !xInvocation.is() ) throw RuntimeException("XInvocation2 not implemented, cannot interact with object"); + + if (bCheckExisting) + { + Reference<XUnoTunnel> xUnoTunnel ( + xInvocation->getIntrospection()->queryAdapter(cppu::UnoType<XUnoTunnel>::get()), UNO_QUERY ); + if( xUnoTunnel.is() ) + { + sal_Int64 that = xUnoTunnel->getSomething( ::pyuno::Adapter::getUnoTunnelImplementationId() ); + if( that ) + return PyRef( reinterpret_cast<Adapter*>(that)->getWrappedObject() ); + } } } - if (!tmp_interface.is()) - { - Py_INCREF( Py_None ); - return Py_None; - } + if( !Py_IsInitialized() ) + throw RuntimeException(); + PyUNO* self = PyObject_New (PyUNO, &PyUNOType); if (self == NULL) - return NULL; // == error + return PyRef(); // == error self->members = new PyUNOInternals(); - self->members->xInvocation = tmp_invocation; + self->members->xInvocation = xInvocation; self->members->wrappedObject = targetInterface; - return reinterpret_cast<PyObject*>(self); + return PyRef( reinterpret_cast<PyObject*>(self), SAL_NO_ACQUIRE ); + } } diff --git a/pyuno/source/module/pyuno_adapter.cxx b/pyuno/source/module/pyuno_adapter.cxx index 1fbfcba1b48b..ce4995d41eaa 100644 --- a/pyuno/source/module/pyuno_adapter.cxx +++ b/pyuno/source/module/pyuno_adapter.cxx @@ -80,6 +80,9 @@ sal_Int64 Adapter::getSomething( const Sequence< sal_Int8 > &id) throw (RuntimeE void raiseInvocationTargetExceptionWhenNeeded( const Runtime &runtime ) throw ( InvocationTargetException ) { + if( !Py_IsInitialized() ) + throw InvocationTargetException(); + if( PyErr_Occurred() ) { PyRef excType, excValue, excTraceback; @@ -195,6 +198,9 @@ Any Adapter::invoke( const OUString &aFunctionName, { PyThreadAttach guard( mInterpreter ); { + if( !Py_IsInitialized() ) + throw InvocationTargetException(); + // convert parameters to python args // TODO: Out parameter Runtime runtime; @@ -219,12 +225,18 @@ Any Adapter::invoke( const OUString &aFunctionName, for( i = 0; i < size ; i ++ ) { PyRef val = runtime.any2PyObject( aParams[i] ); + + // any2PyObject() can release the GIL + if( !Py_IsInitialized() ) + throw InvocationTargetException(); + PyTuple_SetItem( argsTuple.get(), i, val.getAcquired() ); } // get callable PyRef method(PyObject_GetAttrString( mWrappedObject.get(), TO_ASCII(aFunctionName)), SAL_NO_ACQUIRE); + raiseInvocationTargetExceptionWhenNeeded( runtime); if( !method.is() ) { @@ -355,9 +367,16 @@ void Adapter::setValue( const OUString & aPropertyName, const Any & value ) PyThreadAttach guard( mInterpreter ); try { + if( !Py_IsInitialized() ) + throw InvocationTargetException(); + Runtime runtime; PyRef obj = runtime.any2PyObject( value ); + // any2PyObject() can release the GIL + if( !Py_IsInitialized() ) + throw InvocationTargetException(); + PyObject_SetAttrString( mWrappedObject.get(), TO_ASCII(aPropertyName), obj.get() ); raiseInvocationTargetExceptionWhenNeeded( runtime); @@ -375,6 +394,10 @@ Any Adapter::getValue( const OUString & aPropertyName ) Any ret; PyThreadAttach guard( mInterpreter ); { + // Should probably be InvocationTargetException, but the interface doesn't allow it + if( !Py_IsInitialized() ) + throw RuntimeException(); + Runtime runtime; PyRef pyRef( PyObject_GetAttrString( mWrappedObject.get(), TO_ASCII(aPropertyName) ), @@ -404,6 +427,10 @@ sal_Bool Adapter::hasProperty( const OUString & aPropertyName ) bool bRet = false; PyThreadAttach guard( mInterpreter ); { + // Should probably be InvocationTargetException, but the interface doesn't allow it + if( !Py_IsInitialized() ) + throw RuntimeException(); + bRet = PyObject_HasAttrString( mWrappedObject.get() , TO_ASCII( aPropertyName )); } diff --git a/pyuno/source/module/pyuno_impl.hxx b/pyuno/source/module/pyuno_impl.hxx index 11fbfa27e73f..669386f090e0 100644 --- a/pyuno/source/module/pyuno_impl.hxx +++ b/pyuno/source/module/pyuno_impl.hxx @@ -205,13 +205,10 @@ typedef std::unordered_set< PyRef , PyRef::Hash , std::equal_to<PyRef> > ClassSe int PyUNO_initType(); -PyObject* PyUNO_new( +PyRef PyUNO_new ( const com::sun::star::uno::Any & targetInterface, - const com::sun::star::uno::Reference<com::sun::star::lang::XSingleServiceFactory> & ssf); - -PyObject* PyUNO_new_UNCHECKED ( - const com::sun::star::uno::Any & targetInterface, - const com::sun::star::uno::Reference<com::sun::star::lang::XSingleServiceFactory> & ssf); + const com::sun::star::uno::Reference<com::sun::star::lang::XSingleServiceFactory> & ssf, + const bool bCheckExisting ); typedef struct { diff --git a/pyuno/source/module/pyuno_module.cxx b/pyuno/source/module/pyuno_module.cxx index 722e9226b1a7..7d282c2f27c7 100644 --- a/pyuno/source/module/pyuno_module.cxx +++ b/pyuno/source/module/pyuno_module.cxx @@ -406,8 +406,8 @@ static PyObject *createUnoStructHelper( if (idl_class.is ()) { idl_class->createObject (IdlStruct); - PyUNO *me = reinterpret_cast<PyUNO*>(PyUNO_new_UNCHECKED( IdlStruct, c->xInvocation )); - PyRef returnCandidate( reinterpret_cast<PyObject*>(me), SAL_NO_ACQUIRE ); + PyRef returnCandidate( PyUNO_new( IdlStruct, c->xInvocation, false ) ); + PyUNO *me = reinterpret_cast<PyUNO*>( returnCandidate.get() ); TypeDescription desc( typeName ); OSL_ASSERT( desc.is() ); // could already instantiate an XInvocation2 ! diff --git a/pyuno/source/module/pyuno_runtime.cxx b/pyuno/source/module/pyuno_runtime.cxx index cda8e8b1b669..f14b84b4baa7 100644 --- a/pyuno/source/module/pyuno_runtime.cxx +++ b/pyuno/source/module/pyuno_runtime.cxx @@ -481,7 +481,7 @@ PyRef Runtime::any2PyObject (const Any &a ) const case typelib_TypeClass_STRUCT: { PyRef excClass = getClass( a.getValueType().getTypeName(), *this ); - PyRef value = PyRef( PyUNO_new_UNCHECKED (a, getImpl()->cargo->xInvocation), SAL_NO_ACQUIRE); + PyRef value = PyUNO_new( a, getImpl()->cargo->xInvocation, false ); PyRef argsTuple( PyTuple_New( 1 ) , SAL_NO_ACQUIRE, NOT_NULL ); PyTuple_SetItem( argsTuple.get() , 0 , value.getAcquired() ); PyRef ret( PyObject_CallObject( excClass.get() , argsTuple.get() ), SAL_NO_ACQUIRE ); @@ -551,22 +551,12 @@ PyRef Runtime::any2PyObject (const Any &a ) const } case typelib_TypeClass_INTERFACE: { - // fdo#46678 must unlock GIL because getSomething could acquire locks, - // and queryInterface too... - { - PyThreadDetach d; + Reference<XInterface> tmp_interface; + a >>= tmp_interface; + if (!tmp_interface.is ()) + return Py_None; - Reference<XUnoTunnel> tunnel; - a >>= tunnel; - if (tunnel.is()) - { - sal_Int64 that = tunnel->getSomething( ::pyuno::Adapter::getUnoTunnelImplementationId() ); - if( that ) - return reinterpret_cast<Adapter*>(that)->getWrappedObject(); - } - } - //This is just like the struct case: - return PyRef( PyUNO_new (a, getImpl()->cargo->xInvocation), SAL_NO_ACQUIRE ); + return PyUNO_new (a, getImpl()->cargo->xInvocation, true); } default: { |