/* -*- Mode: C++; eval:(c-set-style "bsd"); tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
using com::sun::star::uno::Reference; using com::sun::star::uno::XInterface; using com::sun::star::uno::Any; using com::sun::star::uno::TypeDescription; using com::sun::star::uno::Sequence; using com::sun::star::uno::Type; using com::sun::star::uno::UNO_QUERY; using com::sun::star::uno::Exception; using com::sun::star::uno::RuntimeException; using com::sun::star::uno::XComponentContext; using com::sun::star::lang::WrappedTargetRuntimeException; using com::sun::star::lang::XSingleServiceFactory; using com::sun::star::lang::XUnoTunnel; using com::sun::star::reflection::theCoreReflection; using com::sun::star::reflection::InvocationTargetException; using com::sun::star::script::Converter; using com::sun::star::script::XTypeConverter; using com::sun::star::script::XInvocation; using com::sun::star::beans::XMaterialHolder; using com::sun::star::beans::theIntrospection;
/*---------------------------------------------------------------------- Runtime implementation
-----------------------------------------------------------------------*/ /// @throws css::uno::RuntimeException staticvoid getRuntimeImpl( PyRef & globalDict, PyRef &runtimeImpl )
{
PyThreadState * state = PyThreadState_Get(); if( ! state )
{ throw RuntimeException( u"python global interpreter must be held (thread must be attached)"_ustr );
}
/// @throws RuntimeException static PyRef importUnoModule( )
{ // import the uno module
PyRef module( PyImport_ImportModule( "uno" ), SAL_NO_ACQUIRE, NOT_NULL ); if( PyErr_Occurred() )
{
PyRef excType, excValue, excTraceback;
PyErr_Fetch( reinterpret_cast<PyObject **>(&excType), reinterpret_cast<PyObject**>(&excValue), reinterpret_cast<PyObject**>(&excTraceback)); // As of Python 2.7 this gives a rather non-useful "<traceback object at 0xADDRESS>", // but it is the best we can do in the absence of uno._uno_extract_printable_stacktrace // Who knows, a future Python might print something better.
PyRef str( PyObject_Str( excTraceback.get() ), SAL_NO_ACQUIRE );
PyRef Runtime::any2PyObject (const Any &a ) const
{ if( ! impl->cargo->valid )
{ throw RuntimeException(u"pyuno runtime must be initialized before calling any2PyObject"_ustr );
}
switch (a.getValueTypeClass ())
{ case css::uno::TypeClass_VOID:
{
Py_INCREF (Py_None); return PyRef(Py_None);
} case css::uno::TypeClass_CHAR:
{
sal_Unicode c = *o3tl::forceAccess<sal_Unicode>(a); return PyRef( PyUNO_char_new( c , *this ), SAL_NO_ACQUIRE );
} case css::uno::TypeClass_BOOLEAN:
{ bool b; if ((a >>= b) && b) return Py_True; else return Py_False;
} case css::uno::TypeClass_BYTE: case css::uno::TypeClass_SHORT: case css::uno::TypeClass_UNSIGNED_SHORT: case css::uno::TypeClass_LONG:
{
sal_Int32 l = 0;
a >>= l; return PyRef( PyLong_FromLong (l), SAL_NO_ACQUIRE );
} case css::uno::TypeClass_UNSIGNED_LONG:
{
sal_uInt32 l = 0;
a >>= l; return PyRef( PyLong_FromUnsignedLong (l), SAL_NO_ACQUIRE );
} case css::uno::TypeClass_HYPER:
{
sal_Int64 l = 0;
a >>= l; return PyRef( PyLong_FromLongLong (l), SAL_NO_ACQUIRE);
} case css::uno::TypeClass_UNSIGNED_HYPER:
{
sal_uInt64 l = 0;
a >>= l; return PyRef( PyLong_FromUnsignedLongLong (l), SAL_NO_ACQUIRE);
} case css::uno::TypeClass_FLOAT:
{ float f = 0.0;
a >>= f; return PyRef(PyFloat_FromDouble (f), SAL_NO_ACQUIRE);
} case css::uno::TypeClass_DOUBLE:
{ double d = 0.0;
a >>= d; return PyRef( PyFloat_FromDouble (d), SAL_NO_ACQUIRE);
} case css::uno::TypeClass_STRING:
{
OUString tmp_ostr;
a >>= tmp_ostr; return ustring2PyUnicode( tmp_ostr );
} case css::uno::TypeClass_TYPE:
{
Type t;
a >>= t;
OString o = OUStringToOString( t.getTypeName(), RTL_TEXTENCODING_ASCII_US ); return PyRef(
PyUNO_Type_new (
o.getStr(), t.getTypeClass(), *this),
SAL_NO_ACQUIRE);
} case css::uno::TypeClass_ANY:
{ //I don't think this can happen.
Py_INCREF (Py_None); return Py_None;
} case css::uno::TypeClass_ENUM:
{
sal_Int32 l = *static_cast<sal_Int32 const *>(a.getValue());
TypeDescription desc( a.getValueType() ); if( desc.is() )
{
desc.makeComplete();
typelib_EnumTypeDescription *pEnumDesc = reinterpret_cast<typelib_EnumTypeDescription *>(desc.get()); for( int i = 0 ; i < pEnumDesc->nEnumValues ; i ++ )
{ if( pEnumDesc->pEnumValues[i] == l )
{
OString v = OUStringToOString( OUString::unacquired(&pEnumDesc->ppEnumNames[i]), RTL_TEXTENCODING_ASCII_US);
OString e = OUStringToOString( OUString::unacquired(&pEnumDesc->aBase.pTypeName), RTL_TEXTENCODING_ASCII_US); return PyRef( PyUNO_Enum_new(e.getStr(),v.getStr(), *this ), SAL_NO_ACQUIRE );
}
}
} throw RuntimeException( "Any carries enum " + a.getValueTypeName() + " with invalid value " + OUString::number(l) );
} case css::uno::TypeClass_EXCEPTION: case css::uno::TypeClass_STRUCT:
{
PyRef excClass = getClass( a.getValueTypeName(), *this );
PyRef value = PyUNOStruct_new( a, getImpl()->cargo->xInvocation );
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 ); if( ! ret.is() )
{ throw RuntimeException( "Couldn't instantiate python representation of structured UNO type " +
a.getValueTypeName() );
}
if( auto e = o3tl::tryAccess<css::uno::Exception>(a) )
{ // add the message in a standard python way !
PyRef args( PyTuple_New( 1 ), SAL_NO_ACQUIRE, NOT_NULL );
PyRef pymsg = ustring2PyString( e->Message );
PyTuple_SetItem( args.get(), 0 , pymsg.getAcquired() ); // the exception base functions want to have an "args" tuple, // which contains the message
PyObject_SetAttrString( ret.get(), "args", args.get() );
} return ret;
} case css::uno::TypeClass_SEQUENCE:
{
Sequence<Any> s;
Sequence< sal_Int8 > byteSequence; if( a >>= byteSequence )
{ // byte sequence is treated in a special way because of performance reasons // @since 0.9.2 return PyRef( PyUNO_ByteSequence_new( byteSequence, *this ), SAL_NO_ACQUIRE );
} else
{
Reference< XTypeConverter > tc = getImpl()->cargo->xTypeConverter;
tc->convertTo (a, cppu::UnoType<decltype(s)>::get()) >>= s;
PyRef tuple( PyTuple_New (s.getLength()), SAL_NO_ACQUIRE, NOT_NULL); int i=0; try
{ for ( i = 0; i < s.getLength (); i++)
{
PyRef element = any2PyObject (tc->convertTo (s[i], s[i].getValueType() ));
OSL_ASSERT( element.is() );
PyTuple_SetItem( tuple.get(), i, element.getAcquired() );
}
} catch( css::uno::Exception & )
{ for( ; i < s.getLength() ; i ++ )
{
Py_INCREF( Py_None );
PyTuple_SetItem( tuple.get(), i, Py_None );
} throw;
} return tuple;
}
} case css::uno::TypeClass_INTERFACE:
{
Reference<XInterface> tmp_interface;
a >>= tmp_interface; if (!tmp_interface.is ()) return Py_None;
return PyUNO_new( a, getImpl()->cargo->xInvocation );
} default:
{ throw RuntimeException( "Unknown UNO type class " + OUString::number(static_cast<int>(a.getValueTypeClass())) );
}
}
}
static Sequence< Type > invokeGetTypes( const Runtime & r , PyObject * o )
{
Sequence< Type > ret;
// add the XUnoTunnel interface for uno object identity concept (hack)
ret.realloc( size + 1 ); auto pret = ret.getArray(); for( int i = 0 ; i < size ; i ++ )
{
Any a = r.pyObject2Any(PyTuple_GetItem(types.get(),i));
a >>= pret[i];
}
pret[size] = cppu::UnoType<css::lang::XUnoTunnel>::get();
}
} return ret;
}
static OUString
lcl_ExceptionMessage(PyObject *const o, OUString const*const pWrapped)
{
OUStringBuffer buf;
buf.append("Couldn't convert ");
PyRef reprString( PyObject_Str(o), SAL_NO_ACQUIRE );
buf.appendAscii( PyUnicode_AsUTF8(reprString.get()) );
buf.append(" to a UNO type"); if (pWrapped)
{
buf.append("; caught exception: ");
buf.append(*pWrapped);
} return buf.makeStringAndClear();
}
// For Python 2.7 - see https://bugs.python.org/issue24161 // Fills aSeq and returns true if pObj is a valid iterator bool Runtime::pyIterUnpack( PyObject *const pObj, Any &a ) const
{ if( !PyIter_Check( pObj )) returnfalse;
// instance already mapped out to the world ?
PyRef2Adapter::iterator ii = impl->cargo->mappedObjects.find( PyRef( o ) ); if( ii != impl->cargo->mappedObjects.end() )
{
adapterObject = ii->second;
}
PyThreadAttach::PyThreadAttach( PyInterpreterState *interp)
: m_isNewState(false)
{ // note: *may* be called recursively, with PyThreadDetach between - in // that case, don't create *new* PyThreadState but reuse!
tstate = PyGILState_GetThisThreadState(); // from TLS, possibly detached if (!tstate)
{
m_isNewState = true;
tstate = PyThreadState_New( interp );
} if( !tstate ) throw RuntimeException( u"Couldn't create a pythreadstate"_ustr );
PyEval_AcquireThread( tstate);
}
PyThreadAttach::~PyThreadAttach()
{ if (m_isNewState)
{ // Clear needs GIL!
PyThreadState_Clear( tstate ); // note: PyThreadState_Delete(tstate) cannot be called, it will assert // because it requires a PyThreadState to be set, but not the tstate!
PyThreadState_DeleteCurrent();
} else
{
PyEval_ReleaseThread( tstate );
}
}
PyThreadDetach::PyThreadDetach()
{
tstate = PyThreadState_Get();
PyEval_ReleaseThread( tstate ); // tstate must not be deleted here! lots of pointers to it on the stack
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.