summaryrefslogtreecommitdiff
path: root/pyuno/source/module/pyuno_runtime.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'pyuno/source/module/pyuno_runtime.cxx')
-rw-r--r--pyuno/source/module/pyuno_runtime.cxx1058
1 files changed, 1058 insertions, 0 deletions
diff --git a/pyuno/source/module/pyuno_runtime.cxx b/pyuno/source/module/pyuno_runtime.cxx
new file mode 100644
index 000000000000..754ce05e599e
--- /dev/null
+++ b/pyuno/source/module/pyuno_runtime.cxx
@@ -0,0 +1,1058 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "pyuno_impl.hxx"
+
+#include <osl/thread.h>
+#include <osl/module.h>
+#include <osl/process.h>
+#include <rtl/strbuf.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/bootstrap.hxx>
+#include <locale.h>
+
+#include <typelib/typedescription.hxx>
+
+#include <com/sun/star/beans/XMaterialHolder.hpp>
+
+using rtl::OUString;
+using rtl::OUStringToOString;
+using rtl::OUStringBuffer;
+using rtl::OStringBuffer;
+using rtl::OString;
+
+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::RuntimeException;
+using com::sun::star::uno::XComponentContext;
+using com::sun::star::lang::XSingleServiceFactory;
+using com::sun::star::lang::XUnoTunnel;
+using com::sun::star::reflection::XIdlReflection;
+using com::sun::star::script::XTypeConverter;
+using com::sun::star::script::XInvocationAdapterFactory2;
+using com::sun::star::script::XInvocation;
+using com::sun::star::beans::XMaterialHolder;
+using com::sun::star::beans::XIntrospection;
+
+namespace pyuno
+{
+#define USTR_ASCII(x) OUString( RTL_CONSTASCII_USTRINGPARAM( x ) )
+
+static PyTypeObject RuntimeImpl_Type =
+{
+ PyObject_HEAD_INIT (&PyType_Type)
+ 0,
+ const_cast< char * >("pyuno_runtime"),
+ sizeof (RuntimeImpl),
+ 0,
+ (destructor) RuntimeImpl::del,
+ (printfunc) 0,
+ (getattrfunc) 0,
+ (setattrfunc) 0,
+ (cmpfunc) 0,
+ (reprfunc) 0,
+ 0,
+ 0,
+ 0,
+ (hashfunc) 0,
+ (ternaryfunc) 0,
+ (reprfunc) 0,
+ (getattrofunc)0,
+ (setattrofunc)0,
+ NULL,
+ 0,
+ NULL,
+ (traverseproc)0,
+ (inquiry)0,
+ (richcmpfunc)0,
+ 0,
+ (getiterfunc)0,
+ (iternextfunc)0,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ (descrgetfunc)0,
+ (descrsetfunc)0,
+ 0,
+ (initproc)0,
+ (allocfunc)0,
+ (newfunc)0,
+ (freefunc)0,
+ (inquiry)0,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ (destructor)0
+#if PY_VERSION_HEX >= 0x02060000
+ , 0
+#endif
+};
+
+/*----------------------------------------------------------------------
+ Runtime implementation
+ -----------------------------------------------------------------------*/
+static void getRuntimeImpl( PyRef & globalDict, PyRef &runtimeImpl )
+ throw ( com::sun::star::uno::RuntimeException )
+{
+ PyThreadState * state = PyThreadState_Get();
+ if( ! state )
+ {
+ throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "python global interpreter must be held (thread must be attached)" )),
+ Reference< XInterface > () );
+ }
+
+ globalDict = PyRef( PyModule_GetDict(PyImport_AddModule(const_cast< char * >("__main__"))));
+
+ if( ! globalDict.is() ) // FATAL !
+ {
+ throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "can't find __main__ module" )), Reference< XInterface > ());
+ }
+ runtimeImpl = PyDict_GetItemString( globalDict.get() , "pyuno_runtime" );
+}
+
+static PyRef importUnoModule( ) throw ( RuntimeException )
+{
+ PyRef globalDict = PyRef( PyModule_GetDict(PyImport_AddModule(const_cast< char * >("__main__"))));
+ // import the uno module
+ PyRef module( PyImport_ImportModule( const_cast< char * >("uno") ), SAL_NO_ACQUIRE );
+ if( PyErr_Occurred() )
+ {
+ PyRef excType, excValue, excTraceback;
+ PyErr_Fetch( (PyObject **)&excType, (PyObject**)&excValue,(PyObject**)&excTraceback);
+ PyRef str( PyObject_Repr( excTraceback.get() ), SAL_NO_ACQUIRE );
+
+ OUStringBuffer buf;
+ buf.appendAscii( "python object raised an unknown exception (" );
+ PyRef valueRep( PyObject_Repr( excValue.get() ), SAL_NO_ACQUIRE );
+ buf.appendAscii( PyString_AsString( valueRep.get())).appendAscii( ", traceback follows\n" );
+ buf.appendAscii( PyString_AsString( str.get() ) );
+ throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface > () );
+ }
+ PyRef dict( PyModule_GetDict( module.get() ) );
+ return dict;
+}
+
+static void readLoggingConfig( sal_Int32 *pLevel, FILE **ppFile )
+{
+ *pLevel = LogLevel::NONE;
+ *ppFile = 0;
+ OUString fileName;
+ osl_getModuleURLFromFunctionAddress(
+ reinterpret_cast< oslGenericFunction >(readLoggingConfig),
+ (rtl_uString **) &fileName );
+ fileName = OUString( fileName.getStr(), fileName.lastIndexOf( '/' )+1 );
+ fileName += OUString::createFromAscii( SAL_CONFIGFILE("pyuno") );
+ rtl::Bootstrap bootstrapHandle( fileName );
+
+ OUString str;
+ if( bootstrapHandle.getFrom( USTR_ASCII( "PYUNO_LOGLEVEL" ), str ) )
+ {
+ if( str.equalsAscii( "NONE" ) )
+ *pLevel = LogLevel::NONE;
+ else if( str.equalsAscii( "CALL" ) )
+ *pLevel = LogLevel::CALL;
+ else if( str.equalsAscii( "ARGS" ) )
+ *pLevel = LogLevel::ARGS;
+ else
+ {
+ fprintf( stderr, "unknown loglevel %s\n",
+ OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+ }
+ if( *pLevel > LogLevel::NONE )
+ {
+ *ppFile = stdout;
+ if( bootstrapHandle.getFrom( USTR_ASCII( "PYUNO_LOGTARGET" ), str ) )
+ {
+ if( str.equalsAscii( "stdout" ) )
+ *ppFile = stdout;
+ else if( str.equalsAscii( "stderr" ) )
+ *ppFile = stderr;
+ else
+ {
+ oslProcessInfo data;
+ data.Size = sizeof( data );
+ osl_getProcessInfo(
+ 0 , osl_Process_IDENTIFIER , &data );
+ osl_getSystemPathFromFileURL( str.pData, &str.pData);
+ OString o = OUStringToOString( str, osl_getThreadTextEncoding() );
+ o += ".";
+ o += OString::valueOf( (sal_Int32)data.Ident );
+
+ *ppFile = fopen( o.getStr() , "w" );
+ if ( *ppFile )
+ {
+ // do not buffer (useful if e.g. analyzing a crash)
+ setvbuf( *ppFile, 0, _IONBF, 0 );
+ }
+ else
+ {
+ fprintf( stderr, "couldn't create file %s\n",
+ OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
+
+ }
+ }
+ }
+ }
+}
+
+/*-------------------------------------------------------------------
+ RuntimeImpl implementations
+ *-------------------------------------------------------------------*/
+PyRef stRuntimeImpl::create( const Reference< XComponentContext > &ctx )
+ throw( com::sun::star::uno::RuntimeException )
+{
+ RuntimeImpl *me = PyObject_New (RuntimeImpl, &RuntimeImpl_Type);
+ if( ! me )
+ throw RuntimeException(
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "cannot instantiate pyuno::RuntimeImpl" ) ),
+ Reference< XInterface > () );
+ me->cargo = 0;
+ // must use a different struct here, as the PyObject_New
+ // makes C++ unusable
+ RuntimeCargo *c = new RuntimeCargo();
+ readLoggingConfig( &(c->logLevel) , &(c->logFile) );
+ log( c, LogLevel::CALL, "Instantiating pyuno bridge" );
+
+ c->valid = 1;
+ c->xContext = ctx;
+ c->xInvocation = Reference< XSingleServiceFactory > (
+ ctx->getServiceManager()->createInstanceWithContext(
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.script.Invocation" ) ),
+ ctx ),
+ UNO_QUERY );
+ if( ! c->xInvocation.is() )
+ throw RuntimeException(
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "pyuno: couldn't instantiate invocation service" ) ),
+ Reference< XInterface > () );
+
+ c->xTypeConverter = Reference< XTypeConverter > (
+ ctx->getServiceManager()->createInstanceWithContext(
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.script.Converter" ) ),
+ ctx ),
+ UNO_QUERY );
+ if( ! c->xTypeConverter.is() )
+ throw RuntimeException(
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "pyuno: couldn't instantiate typeconverter service" )),
+ Reference< XInterface > () );
+
+ c->xCoreReflection = Reference< XIdlReflection > (
+ ctx->getServiceManager()->createInstanceWithContext(
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.reflection.CoreReflection" ) ),
+ ctx ),
+ UNO_QUERY );
+ if( ! c->xCoreReflection.is() )
+ throw RuntimeException(
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "pyuno: couldn't instantiate corereflection service" )),
+ Reference< XInterface > () );
+
+ c->xAdapterFactory = Reference< XInvocationAdapterFactory2 > (
+ ctx->getServiceManager()->createInstanceWithContext(
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.script.InvocationAdapterFactory" ) ),
+ ctx ),
+ UNO_QUERY );
+ if( ! c->xAdapterFactory.is() )
+ throw RuntimeException(
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "pyuno: couldn't instantiate invocation adapter factory service" )),
+ Reference< XInterface > () );
+
+ c->xIntrospection = Reference< XIntrospection > (
+ ctx->getServiceManager()->createInstanceWithContext(
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.beans.Introspection" ) ),
+ ctx ),
+ UNO_QUERY );
+ if( ! c->xIntrospection.is() )
+ throw RuntimeException(
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "pyuno: couldn't instantiate introspection service" )),
+ Reference< XInterface > () );
+
+ Any a = ctx->getValueByName(OUString(
+ RTL_CONSTASCII_USTRINGPARAM("/singletons/com.sun.star.reflection.theTypeDescriptionManager" )) );
+ a >>= c->xTdMgr;
+ if( ! c->xTdMgr.is() )
+ throw RuntimeException(
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "pyuno: couldn't retrieve typedescriptionmanager" )),
+ Reference< XInterface > () );
+
+ me->cargo =c;
+ return PyRef( reinterpret_cast< PyObject * > ( me ), SAL_NO_ACQUIRE );
+}
+
+void stRuntimeImpl::del(PyObject* self)
+{
+ RuntimeImpl *me = reinterpret_cast< RuntimeImpl * > ( self );
+ if( me->cargo->logFile )
+ fclose( me->cargo->logFile );
+ delete me->cargo;
+ PyObject_Del (self);
+}
+
+
+void Runtime::initialize( const Reference< XComponentContext > & ctx )
+ throw ( RuntimeException )
+{
+ PyRef globalDict, runtime;
+ getRuntimeImpl( globalDict , runtime );
+ RuntimeImpl *impl = reinterpret_cast< RuntimeImpl * > (runtime.get());
+
+ if( runtime.is() && impl->cargo->valid )
+ {
+ throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "pyuno runtime has already been initialized before" ) ),
+ Reference< XInterface > () );
+ }
+ PyRef keep( RuntimeImpl::create( ctx ) );
+ PyDict_SetItemString( globalDict.get(), "pyuno_runtime" , keep.get() );
+ Py_XINCREF( keep.get() );
+}
+
+
+bool Runtime::isInitialized() throw ( RuntimeException )
+{
+ PyRef globalDict, runtime;
+ getRuntimeImpl( globalDict , runtime );
+ RuntimeImpl *impl = reinterpret_cast< RuntimeImpl * > (runtime.get());
+ return runtime.is() && impl->cargo->valid;
+}
+
+void Runtime::finalize() throw (RuntimeException)
+{
+ PyRef globalDict, runtime;
+ getRuntimeImpl( globalDict , runtime );
+ RuntimeImpl *impl = reinterpret_cast< RuntimeImpl * > (runtime.get());
+ if( !runtime.is() || ! impl->cargo->valid )
+ {
+ throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "pyuno bridge must have been initialized before finalizing" )),
+ Reference< XInterface > () );
+ }
+ impl->cargo->valid = false;
+ impl->cargo->xInvocation.clear();
+ impl->cargo->xContext.clear();
+ impl->cargo->xTypeConverter.clear();
+}
+
+Runtime::Runtime() throw( RuntimeException )
+ : impl( 0 )
+{
+ PyRef globalDict, runtime;
+ getRuntimeImpl( globalDict , runtime );
+ if( ! runtime.is() )
+ {
+ throw RuntimeException(
+ OUString( RTL_CONSTASCII_USTRINGPARAM("pyuno runtime is not initialized, "
+ "(the pyuno.bootstrap needs to be called before using any uno classes)")),
+ Reference< XInterface > () );
+ }
+ impl = reinterpret_cast< RuntimeImpl * > (runtime.get());
+ Py_XINCREF( runtime.get() );
+}
+
+Runtime::Runtime( const Runtime & r )
+{
+ impl = r.impl;
+ Py_XINCREF( reinterpret_cast< PyObject * >(impl) );
+}
+
+Runtime::~Runtime()
+{
+ Py_XDECREF( reinterpret_cast< PyObject * >(impl) );
+}
+
+Runtime & Runtime::operator = ( const Runtime & r )
+{
+ PyRef temp( reinterpret_cast< PyObject * >(r.impl) );
+ Py_XINCREF( temp.get() );
+ Py_XDECREF( reinterpret_cast< PyObject * >(impl) );
+ impl = r.impl;
+ return *this;
+}
+
+PyRef Runtime::any2PyObject (const Any &a ) const
+ throw ( com::sun::star::script::CannotConvertException,
+ com::sun::star::lang::IllegalArgumentException,
+ RuntimeException)
+{
+ if( ! impl->cargo->valid )
+ {
+ throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "pyuno runtime must be initialized before calling any2PyObject" )),
+ Reference< XInterface > () );
+ }
+
+ switch (a.getValueTypeClass ())
+ {
+ case typelib_TypeClass_VOID:
+ {
+ Py_INCREF (Py_None);
+ return PyRef(Py_None);
+ }
+ case typelib_TypeClass_CHAR:
+ {
+ sal_Unicode c = *(sal_Unicode*)a.getValue();
+ return PyRef( PyUNO_char_new( c , *this ), SAL_NO_ACQUIRE );
+ }
+ case typelib_TypeClass_BOOLEAN:
+ {
+ sal_Bool b = sal_Bool();
+ if ((a >>= b) && b)
+ return Py_True;
+ else
+ return Py_False;
+ }
+ case typelib_TypeClass_BYTE:
+ case typelib_TypeClass_SHORT:
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ case typelib_TypeClass_LONG:
+ {
+ sal_Int32 l = 0;
+ a >>= l;
+ return PyRef( PyInt_FromLong (l), SAL_NO_ACQUIRE );
+ }
+ case typelib_TypeClass_UNSIGNED_LONG:
+ {
+ sal_uInt32 l = 0;
+ a >>= l;
+ return PyRef( PyLong_FromUnsignedLong (l), SAL_NO_ACQUIRE );
+ }
+ case typelib_TypeClass_HYPER:
+ {
+ sal_Int64 l = 0;
+ a >>= l;
+ return PyRef( PyLong_FromLongLong (l), SAL_NO_ACQUIRE);
+ }
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ {
+ sal_uInt64 l = 0;
+ a >>= l;
+ return PyRef( PyLong_FromUnsignedLongLong (l), SAL_NO_ACQUIRE);
+ }
+ case typelib_TypeClass_FLOAT:
+ {
+ float f = 0.0;
+ a >>= f;
+ return PyRef(PyFloat_FromDouble (f), SAL_NO_ACQUIRE);
+ }
+ case typelib_TypeClass_DOUBLE:
+ {
+ double d = 0.0;
+ a >>= d;
+ return PyRef( PyFloat_FromDouble (d), SAL_NO_ACQUIRE);
+ }
+ case typelib_TypeClass_STRING:
+ {
+ OUString tmp_ostr;
+ a >>= tmp_ostr;
+ return ustring2PyUnicode( tmp_ostr );
+ }
+ case typelib_TypeClass_TYPE:
+ {
+ Type t;
+ a >>= t;
+ OString o = OUStringToOString( t.getTypeName(), RTL_TEXTENCODING_ASCII_US );
+ return PyRef(
+ PyUNO_Type_new (
+ o.getStr(), (com::sun::star::uno::TypeClass)t.getTypeClass(), *this),
+ SAL_NO_ACQUIRE);
+ }
+ case typelib_TypeClass_ANY:
+ {
+ //I don't think this can happen.
+ Py_INCREF (Py_None);
+ return Py_None;
+ }
+ case typelib_TypeClass_ENUM:
+ {
+ sal_Int32 l = *(sal_Int32 *) a.getValue();
+ TypeDescription desc( a.getValueType() );
+ if( desc.is() )
+ {
+ desc.makeComplete();
+ typelib_EnumTypeDescription *pEnumDesc =
+ (typelib_EnumTypeDescription *) desc.get();
+ for( int i = 0 ; i < pEnumDesc->nEnumValues ; i ++ )
+ {
+ if( pEnumDesc->pEnumValues[i] == l )
+ {
+ OString v = OUStringToOString( pEnumDesc->ppEnumNames[i], RTL_TEXTENCODING_ASCII_US);
+ OString e = OUStringToOString( pEnumDesc->aBase.pTypeName, RTL_TEXTENCODING_ASCII_US);
+ return PyRef( PyUNO_Enum_new(e.getStr(),v.getStr(), *this ), SAL_NO_ACQUIRE );
+ }
+ }
+ }
+ OUStringBuffer buf;
+ buf.appendAscii( "Any carries enum " );
+ buf.append( a.getValueType().getTypeName());
+ buf.appendAscii( " with invalid value " ).append( l );
+ throw RuntimeException( buf.makeStringAndClear() , Reference< XInterface > () );
+ }
+ case typelib_TypeClass_EXCEPTION:
+ 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 argsTuple( PyTuple_New( 1 ) , SAL_NO_ACQUIRE );
+ PyTuple_SetItem( argsTuple.get() , 0 , value.getAcquired() );
+ PyRef ret( PyObject_CallObject( excClass.get() , argsTuple.get() ), SAL_NO_ACQUIRE );
+ if( ! ret.is() )
+ {
+ OUStringBuffer buf;
+ buf.appendAscii( "Couldn't instantiate python representation of structered UNO type " );
+ buf.append( a.getValueType().getTypeName() );
+ throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface > () );
+ }
+
+ if( com::sun::star::uno::TypeClass_EXCEPTION == a.getValueTypeClass() )
+ {
+ // add the message in a standard python way !
+ PyRef args( PyTuple_New( 1 ), SAL_NO_ACQUIRE );
+
+ // assuming that the Message is always the first member, wuuuu
+ void *pData = (void*)a.getValue();
+ OUString message = *(OUString * )pData;
+ PyRef pymsg = ustring2PyString( 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(), const_cast< char * >("args"), args.get() );
+ }
+ return ret;
+ }
+ case typelib_TypeClass_SEQUENCE:
+ {
+ Sequence<Any> s;
+
+ Sequence< sal_Int8 > byteSequence;
+ if( a >>= byteSequence )
+ {
+ // byte sequence is treated in a special way because of peformance reasons
+ // @since 0.9.2
+ return PyRef( PyUNO_ByteSequence_new( byteSequence, *this ), SAL_NO_ACQUIRE );
+ }
+ else
+ {
+ Reference< XTypeConverter > tc = getImpl()->cargo->xTypeConverter;
+ Reference< XSingleServiceFactory > ssf = getImpl()->cargo->xInvocation;
+ tc->convertTo (a, ::getCppuType (&s)) >>= s;
+ PyRef tuple( PyTuple_New (s.getLength()), SAL_NO_ACQUIRE);
+ int i=0;
+ OUString errMsg;
+ try
+ {
+ for ( i = 0; i < s.getLength (); i++)
+ {
+ PyRef element;
+ element = any2PyObject (tc->convertTo (s[i], s[i].getValueType() ));
+ OSL_ASSERT( element.is() );
+ PyTuple_SetItem( tuple.get(), i, element.getAcquired() );
+ }
+ }
+ catch( com::sun::star::uno::Exception & )
+ {
+ for( ; i < s.getLength() ; i ++ )
+ {
+ Py_INCREF( Py_None );
+ PyTuple_SetItem( tuple.get(), i, Py_None );
+ }
+ throw;
+ }
+ return tuple;
+ }
+ }
+ case typelib_TypeClass_INTERFACE:
+ {
+ Reference< XUnoTunnel > tunnel;
+ a >>= tunnel;
+ if( tunnel.is() )
+ {
+ sal_Int64 that = tunnel->getSomething( ::pyuno::Adapter::getUnoTunnelImplementationId() );
+ if( that )
+ return ((Adapter*)sal::static_int_cast< sal_IntPtr >(that))->getWrappedObject();
+ }
+ //This is just like the struct case:
+ return PyRef( PyUNO_new (a, getImpl()->cargo->xInvocation), SAL_NO_ACQUIRE );
+ }
+ default:
+ {
+ OUStringBuffer buf;
+ buf.appendAscii( "Unknonwn UNO type class " );
+ buf.append( (sal_Int32 ) a.getValueTypeClass() );
+ throw RuntimeException(buf.makeStringAndClear( ), Reference< XInterface > () );
+ }
+ }
+ //We shouldn't be here...
+ Py_INCREF( Py_None );
+ return Py_None;
+}
+
+static Sequence< Type > invokeGetTypes( const Runtime & r , PyObject * o )
+{
+ Sequence< Type > ret;
+
+ PyRef method( PyObject_GetAttrString( o , const_cast< char * >("getTypes") ), SAL_NO_ACQUIRE );
+ raiseInvocationTargetExceptionWhenNeeded( r );
+ if( method.is() && PyCallable_Check( method.get() ) )
+ {
+ PyRef types( PyObject_CallObject( method.get(), 0 ) , SAL_NO_ACQUIRE );
+ raiseInvocationTargetExceptionWhenNeeded( r );
+ if( types.is() && PyTuple_Check( types.get() ) )
+ {
+ int size = PyTuple_Size( types.get() );
+
+ // add the XUnoTunnel interface for uno object identity concept (hack)
+ ret.realloc( size + 1 );
+ for( int i = 0 ; i < size ; i ++ )
+ {
+ Any a = r.pyObject2Any(PyTuple_GetItem(types.get(),i));
+ a >>= ret[i];
+ }
+ ret[size] = getCppuType( (Reference< com::sun::star::lang::XUnoTunnel> *) 0 );
+ }
+ }
+ return ret;
+}
+
+Any Runtime::pyObject2Any ( const PyRef & source, enum ConversionMode mode ) const
+ throw ( com::sun::star::uno::RuntimeException )
+{
+ if( ! impl->cargo->valid )
+ {
+ throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "pyuno runtime must be initialized before calling any2PyObject" )),
+ Reference< XInterface > () );
+ }
+
+ Any a;
+ PyObject *o = source.get();
+ if( Py_None == o )
+ {
+
+ }
+ else if (PyInt_Check (o))
+ {
+ if( o == Py_True )
+ {
+ sal_Bool b = sal_True;
+ a = Any( &b, getBooleanCppuType() );
+ }
+ else if ( o == Py_False )
+ {
+ sal_Bool b = sal_False;
+ a = Any( &b, getBooleanCppuType() );
+ }
+ else
+ {
+ sal_Int32 l = (sal_Int32) PyInt_AsLong( o );
+ if( l < 128 && l >= -128 )
+ {
+ sal_Int8 b = (sal_Int8 ) l;
+ a <<= b;
+ }
+ else if( l <= 0x7fff && l >= -0x8000 )
+ {
+ sal_Int16 s = (sal_Int16) l;
+ a <<= s;
+ }
+ else
+ {
+ a <<= l;
+ }
+ }
+ }
+ else if (PyLong_Check (o))
+ {
+ sal_Int64 l = (sal_Int64)PyLong_AsLong (o);
+ if( l < 128 && l >= -128 )
+ {
+ sal_Int8 b = (sal_Int8 ) l;
+ a <<= b;
+ }
+ else if( l <= 0x7fff && l >= -0x8000 )
+ {
+ sal_Int16 s = (sal_Int16) l;
+ a <<= s;
+ }
+ else if( l <= SAL_CONST_INT64(0x7fffffff) &&
+ l >= -SAL_CONST_INT64(0x80000000) )
+ {
+ sal_Int32 l32 = (sal_Int32) l;
+ a <<= l32;
+ }
+ else
+ {
+ a <<= l;
+ }
+ }
+ else if (PyFloat_Check (o))
+ {
+ double d = PyFloat_AsDouble (o);
+ a <<= d;
+ }
+ else if (PyString_Check (o))
+ a <<= pyString2ustring(o);
+ else if( PyUnicode_Check( o ) )
+ a <<= pyString2ustring(o);
+ else if (PyTuple_Check (o))
+ {
+ Sequence<Any> s (PyTuple_Size (o));
+ for (int i = 0; i < PyTuple_Size (o); i++)
+ {
+ s[i] = pyObject2Any (PyTuple_GetItem (o, i), mode );
+ }
+ a <<= s;
+ }
+ else
+ {
+ Runtime runtime;
+ // should be removed, in case ByteSequence gets derived from String
+ if( PyObject_IsInstance( o, getByteSequenceClass( runtime ).get() ) )
+ {
+ PyRef str(PyObject_GetAttrString( o , const_cast< char * >("value") ),SAL_NO_ACQUIRE);
+ Sequence< sal_Int8 > seq;
+ if( PyString_Check( str.get() ) )
+ {
+ seq = Sequence<sal_Int8 > (
+ (sal_Int8*) PyString_AsString(str.get()), PyString_Size(str.get()));
+ }
+ a <<= seq;
+ }
+ else
+ if( PyObject_IsInstance( o, getTypeClass( runtime ).get() ) )
+ {
+ Type t = PyType2Type( o );
+ a <<= t;
+ }
+ else if( PyObject_IsInstance( o, getEnumClass( runtime ).get() ) )
+ {
+ a = PyEnum2Enum( o );
+ }
+ else if( isInstanceOfStructOrException( o ) )
+ {
+ PyRef struc(PyObject_GetAttrString( o , const_cast< char * >("value") ),SAL_NO_ACQUIRE);
+ PyUNO * obj = (PyUNO*)struc.get();
+ Reference< XMaterialHolder > holder( obj->members->xInvocation, UNO_QUERY );
+ if( holder.is( ) )
+ a = holder->getMaterial();
+ else
+ {
+ throw RuntimeException(
+ USTR_ASCII( "struct or exception wrapper does not support XMaterialHolder" ),
+ Reference< XInterface > () );
+ }
+ }
+ else if( PyObject_IsInstance( o, getPyUnoClass( runtime ).get() ) )
+ {
+ PyUNO* o_pi;
+ o_pi = (PyUNO*) o;
+ if (o_pi->members->wrappedObject.getValueTypeClass () ==
+ com::sun::star::uno::TypeClass_STRUCT ||
+ o_pi->members->wrappedObject.getValueTypeClass () ==
+ com::sun::star::uno::TypeClass_EXCEPTION)
+ {
+ Reference<XMaterialHolder> my_mh (o_pi->members->xInvocation, UNO_QUERY);
+
+ if (!my_mh.is ())
+ {
+ throw RuntimeException(
+ USTR_ASCII( "struct wrapper does not support XMaterialHolder" ),
+ Reference< XInterface > () );
+ }
+ else
+ a = my_mh->getMaterial ();
+ }
+ else
+ {
+ a = o_pi->members->wrappedObject;
+ }
+ }
+ else if( PyObject_IsInstance( o, getCharClass( runtime ).get() ) )
+ {
+ sal_Unicode c = PyChar2Unicode( o );
+ a.setValue( &c, getCharCppuType( ));
+ }
+ else if( PyObject_IsInstance( o, getAnyClass( runtime ).get() ) )
+ {
+ if( ACCEPT_UNO_ANY == mode )
+ {
+ a = pyObject2Any( PyRef( PyObject_GetAttrString( o , const_cast< char * >("value") ), SAL_NO_ACQUIRE) );
+ Type t;
+ pyObject2Any( PyRef( PyObject_GetAttrString( o, const_cast< char * >("type") ), SAL_NO_ACQUIRE ) ) >>= t;
+
+ try
+ {
+ a = getImpl()->cargo->xTypeConverter->convertTo( a, t );
+ }
+ catch( com::sun::star::uno::Exception & e )
+ {
+ throw RuntimeException( e.Message, e.Context );
+ }
+ }
+ else
+ {
+ throw RuntimeException(
+ OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "uno.Any instance not accepted during method call, "
+ "use uno.invoke instead" ) ),
+ Reference< XInterface > () );
+ }
+ }
+ else
+ {
+ Reference< XInterface > mappedObject;
+ Reference< XInvocation > adapterObject;
+
+ // 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;
+ }
+
+ if( adapterObject.is() )
+ {
+ // object got already bridged !
+ Reference< com::sun::star::lang::XUnoTunnel > tunnel( adapterObject, UNO_QUERY );
+
+ Adapter *pAdapter = ( Adapter * )
+ sal::static_int_cast< sal_IntPtr >(
+ tunnel->getSomething(
+ ::pyuno::Adapter::getUnoTunnelImplementationId() ) );
+
+ mappedObject = impl->cargo->xAdapterFactory->createAdapter(
+ adapterObject, pAdapter->getWrappedTypes() );
+ }
+ else
+ {
+ Sequence< Type > interfaces = invokeGetTypes( *this, o );
+ if( interfaces.getLength() )
+ {
+ Adapter *pAdapter = new Adapter( o, interfaces );
+ mappedObject =
+ getImpl()->cargo->xAdapterFactory->createAdapter(
+ pAdapter, interfaces );
+
+ // keep a list of exported objects to ensure object identity !
+ impl->cargo->mappedObjects[ PyRef(o) ] =
+ com::sun::star::uno::WeakReference< XInvocation > ( pAdapter );
+ }
+ }
+ if( mappedObject.is() )
+ {
+ a = com::sun::star::uno::makeAny( mappedObject );
+ }
+ else
+ {
+ OUStringBuffer buf;
+ buf.appendAscii( "Couldn't convert " );
+ PyRef reprString( PyObject_Str( o ) , SAL_NO_ACQUIRE );
+ buf.appendAscii( PyString_AsString( reprString.get() ) );
+ buf.appendAscii( " to a UNO type" );
+ throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface > () );
+ }
+ }
+ }
+ return a;
+}
+
+Any Runtime::extractUnoException( const PyRef & excType, const PyRef &excValue, const PyRef &excTraceback) const
+{
+ PyRef str;
+ Any ret;
+ if( excTraceback.is() )
+ {
+ PyRef unoModule( impl ? impl->cargo->getUnoModule() : 0 );
+ if( unoModule.is() )
+ {
+ PyRef extractTraceback(
+ PyDict_GetItemString(unoModule.get(),"_uno_extract_printable_stacktrace" ) );
+
+ if( extractTraceback.is() )
+ {
+ PyRef args( PyTuple_New( 1), SAL_NO_ACQUIRE );
+ PyTuple_SetItem( args.get(), 0, excTraceback.getAcquired() );
+ str = PyRef( PyObject_CallObject( extractTraceback.get(),args.get() ), SAL_NO_ACQUIRE);
+ }
+ else
+ {
+ str = PyRef(
+ PyString_FromString( "Couldn't find uno._uno_extract_printable_stacktrace" ),
+ SAL_NO_ACQUIRE );
+ }
+ }
+ else
+ {
+ str = PyRef(
+ PyString_FromString( "Couldn't find uno.py, no stacktrace available" ),
+ SAL_NO_ACQUIRE );
+ }
+
+ }
+ else
+ {
+ // it may occur, that no traceback is given (e.g. only native code below)
+ str = PyRef( PyString_FromString( "no traceback available" ), SAL_NO_ACQUIRE);
+ }
+
+ if( isInstanceOfStructOrException( excValue.get() ) )
+ {
+ ret = pyObject2Any( excValue );
+ }
+ else
+ {
+ OUStringBuffer buf;
+ PyRef typeName( PyObject_Str( excType.get() ), SAL_NO_ACQUIRE );
+ if( typeName.is() )
+ {
+ buf.appendAscii( PyString_AsString( typeName.get() ) );
+ }
+ else
+ {
+ buf.appendAscii( "no typename available" );
+ }
+ buf.appendAscii( ": " );
+ PyRef valueRep( PyObject_Str( excValue.get() ), SAL_NO_ACQUIRE );
+ if( valueRep.is() )
+ {
+ buf.appendAscii( PyString_AsString( valueRep.get()));
+ }
+ else
+ {
+ buf.appendAscii( "Couldn't convert exception value to a string" );
+ }
+ buf.appendAscii( ", traceback follows\n" );
+ if( str.is() )
+ {
+ buf.appendAscii( PyString_AsString( str.get() ) );
+ }
+ else
+ {
+ buf.appendAscii( ", no traceback available\n" );
+ }
+ RuntimeException e;
+ e.Message = buf.makeStringAndClear();
+ ret = com::sun::star::uno::makeAny( e );
+ }
+ return ret;
+}
+
+
+static const char * g_NUMERICID = "pyuno.lcNumeric";
+static ::std::vector< rtl::OString > g_localeList;
+
+static const char *ensureUnlimitedLifetime( const char *str )
+{
+ int size = g_localeList.size();
+ int i;
+ for( i = 0 ; i < size ; i ++ )
+ {
+ if( 0 == strcmp( g_localeList[i].getStr(), str ) )
+ break;
+ }
+ if( i == size )
+ {
+ g_localeList.push_back( str );
+ }
+ return g_localeList[i].getStr();
+}
+
+
+PyThreadAttach::PyThreadAttach( PyInterpreterState *interp)
+ throw ( com::sun::star::uno::RuntimeException )
+{
+ tstate = PyThreadState_New( interp );
+ if( !tstate )
+ throw RuntimeException(
+ OUString(RTL_CONSTASCII_USTRINGPARAM( "Couldn't create a pythreadstate" ) ),
+ Reference< XInterface > () );
+ PyEval_AcquireThread( tstate);
+ // set LC_NUMERIC to "C"
+ const char * oldLocale =
+ ensureUnlimitedLifetime( setlocale( LC_NUMERIC, 0 ) );
+ setlocale( LC_NUMERIC, "C" );
+ PyRef locale( // python requires C locale
+ PyLong_FromVoidPtr( (void*)oldLocale ), SAL_NO_ACQUIRE);
+ PyDict_SetItemString(
+ PyThreadState_GetDict(), g_NUMERICID, locale.get() );
+}
+
+PyThreadAttach::~PyThreadAttach()
+{
+ PyObject *value =
+ PyDict_GetItemString( PyThreadState_GetDict( ), g_NUMERICID );
+ if( value )
+ setlocale( LC_NUMERIC, (const char * ) PyLong_AsVoidPtr( value ) );
+ PyThreadState_Clear( tstate );
+ PyEval_ReleaseThread( tstate );
+ PyThreadState_Delete( tstate );
+
+}
+
+PyThreadDetach::PyThreadDetach() throw ( com::sun::star::uno::RuntimeException )
+{
+ tstate = PyThreadState_Get();
+ PyObject *value =
+ PyDict_GetItemString( PyThreadState_GetDict( ), g_NUMERICID );
+ if( value )
+ setlocale( LC_NUMERIC, (const char * ) PyLong_AsVoidPtr( value ) );
+ PyEval_ReleaseThread( tstate );
+}
+
+ /** Acquires the global interpreter lock again
+
+ */
+PyThreadDetach::~PyThreadDetach()
+{
+ PyEval_AcquireThread( tstate );
+// PyObject *value =
+// PyDict_GetItemString( PyThreadState_GetDict( ), g_NUMERICID );
+
+ // python requires C LC_NUMERIC locale,
+ // always set even when it is already "C"
+ setlocale( LC_NUMERIC, "C" );
+}
+
+
+PyRef RuntimeCargo::getUnoModule()
+{
+ if( ! dictUnoModule.is() )
+ {
+ dictUnoModule = importUnoModule();
+ }
+ return dictUnoModule;
+}
+}