1*67c7d1c1SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*67c7d1c1SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*67c7d1c1SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*67c7d1c1SAndrew Rist  * distributed with this work for additional information
6*67c7d1c1SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*67c7d1c1SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*67c7d1c1SAndrew Rist  * "License"); you may not use this file except in compliance
9*67c7d1c1SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*67c7d1c1SAndrew Rist  *
11*67c7d1c1SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*67c7d1c1SAndrew Rist  *
13*67c7d1c1SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*67c7d1c1SAndrew Rist  * software distributed under the License is distributed on an
15*67c7d1c1SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*67c7d1c1SAndrew Rist  * KIND, either express or implied.  See the License for the
17*67c7d1c1SAndrew Rist  * specific language governing permissions and limitations
18*67c7d1c1SAndrew Rist  * under the License.
19*67c7d1c1SAndrew Rist  *
20*67c7d1c1SAndrew Rist  *************************************************************/
21*67c7d1c1SAndrew Rist 
22*67c7d1c1SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir #include "pyuno_impl.hxx"
25cdf0e10cSrcweir 
26cdf0e10cSrcweir #include <osl/thread.h>
27cdf0e10cSrcweir #include <osl/module.h>
28cdf0e10cSrcweir #include <osl/process.h>
29cdf0e10cSrcweir #include <rtl/strbuf.hxx>
30cdf0e10cSrcweir #include <rtl/ustrbuf.hxx>
31cdf0e10cSrcweir #include <rtl/bootstrap.hxx>
32cdf0e10cSrcweir #include <locale.h>
33cdf0e10cSrcweir 
34cdf0e10cSrcweir #include <typelib/typedescription.hxx>
35cdf0e10cSrcweir 
36cdf0e10cSrcweir #include <com/sun/star/beans/XMaterialHolder.hpp>
37cdf0e10cSrcweir 
38cdf0e10cSrcweir using rtl::OUString;
39cdf0e10cSrcweir using rtl::OUStringToOString;
40cdf0e10cSrcweir using rtl::OUStringBuffer;
41cdf0e10cSrcweir using rtl::OStringBuffer;
42cdf0e10cSrcweir using rtl::OString;
43cdf0e10cSrcweir 
44cdf0e10cSrcweir using com::sun::star::uno::Reference;
45cdf0e10cSrcweir using com::sun::star::uno::XInterface;
46cdf0e10cSrcweir using com::sun::star::uno::Any;
47cdf0e10cSrcweir using com::sun::star::uno::TypeDescription;
48cdf0e10cSrcweir using com::sun::star::uno::Sequence;
49cdf0e10cSrcweir using com::sun::star::uno::Type;
50cdf0e10cSrcweir using com::sun::star::uno::UNO_QUERY;
51cdf0e10cSrcweir using com::sun::star::uno::RuntimeException;
52cdf0e10cSrcweir using com::sun::star::uno::XComponentContext;
53cdf0e10cSrcweir using com::sun::star::lang::XSingleServiceFactory;
54cdf0e10cSrcweir using com::sun::star::lang::XUnoTunnel;
55cdf0e10cSrcweir using com::sun::star::reflection::XIdlReflection;
56cdf0e10cSrcweir using com::sun::star::script::XTypeConverter;
57cdf0e10cSrcweir using com::sun::star::script::XInvocationAdapterFactory2;
58cdf0e10cSrcweir using com::sun::star::script::XInvocation;
59cdf0e10cSrcweir using com::sun::star::beans::XMaterialHolder;
60cdf0e10cSrcweir using com::sun::star::beans::XIntrospection;
61cdf0e10cSrcweir 
62cdf0e10cSrcweir namespace pyuno
63cdf0e10cSrcweir {
64cdf0e10cSrcweir #define USTR_ASCII(x) OUString( RTL_CONSTASCII_USTRINGPARAM( x ) )
65cdf0e10cSrcweir 
66cdf0e10cSrcweir static PyTypeObject RuntimeImpl_Type =
67cdf0e10cSrcweir {
68cdf0e10cSrcweir     PyObject_HEAD_INIT (&PyType_Type)
69cdf0e10cSrcweir     0,
70cdf0e10cSrcweir     const_cast< char * >("pyuno_runtime"),
71cdf0e10cSrcweir     sizeof (RuntimeImpl),
72cdf0e10cSrcweir     0,
73cdf0e10cSrcweir     (destructor) RuntimeImpl::del,
74cdf0e10cSrcweir     (printfunc) 0,
75cdf0e10cSrcweir     (getattrfunc) 0,
76cdf0e10cSrcweir     (setattrfunc) 0,
77cdf0e10cSrcweir     (cmpfunc) 0,
78cdf0e10cSrcweir     (reprfunc) 0,
79cdf0e10cSrcweir     0,
80cdf0e10cSrcweir     0,
81cdf0e10cSrcweir     0,
82cdf0e10cSrcweir     (hashfunc) 0,
83cdf0e10cSrcweir     (ternaryfunc) 0,
84cdf0e10cSrcweir     (reprfunc) 0,
85cdf0e10cSrcweir     (getattrofunc)0,
86cdf0e10cSrcweir     (setattrofunc)0,
87cdf0e10cSrcweir     NULL,
88cdf0e10cSrcweir     0,
89cdf0e10cSrcweir     NULL,
90cdf0e10cSrcweir     (traverseproc)0,
91cdf0e10cSrcweir     (inquiry)0,
92cdf0e10cSrcweir     (richcmpfunc)0,
93cdf0e10cSrcweir     0,
94cdf0e10cSrcweir     (getiterfunc)0,
95cdf0e10cSrcweir     (iternextfunc)0,
96cdf0e10cSrcweir     NULL,
97cdf0e10cSrcweir     NULL,
98cdf0e10cSrcweir     NULL,
99cdf0e10cSrcweir     NULL,
100cdf0e10cSrcweir     NULL,
101cdf0e10cSrcweir     (descrgetfunc)0,
102cdf0e10cSrcweir     (descrsetfunc)0,
103cdf0e10cSrcweir     0,
104cdf0e10cSrcweir     (initproc)0,
105cdf0e10cSrcweir     (allocfunc)0,
106cdf0e10cSrcweir     (newfunc)0,
107cdf0e10cSrcweir     (freefunc)0,
108cdf0e10cSrcweir     (inquiry)0,
109cdf0e10cSrcweir     NULL,
110cdf0e10cSrcweir     NULL,
111cdf0e10cSrcweir     NULL,
112cdf0e10cSrcweir     NULL,
113cdf0e10cSrcweir     NULL,
114cdf0e10cSrcweir     (destructor)0
115cdf0e10cSrcweir #if PY_VERSION_HEX >= 0x02060000
116cdf0e10cSrcweir     , 0
117cdf0e10cSrcweir #endif
118cdf0e10cSrcweir };
119cdf0e10cSrcweir 
120cdf0e10cSrcweir /*----------------------------------------------------------------------
121cdf0e10cSrcweir   Runtime implementation
122cdf0e10cSrcweir  -----------------------------------------------------------------------*/
123cdf0e10cSrcweir static void getRuntimeImpl( PyRef & globalDict, PyRef &runtimeImpl )
124cdf0e10cSrcweir     throw ( com::sun::star::uno::RuntimeException )
125cdf0e10cSrcweir {
126cdf0e10cSrcweir     PyThreadState * state = PyThreadState_Get();
127cdf0e10cSrcweir     if( ! state )
128cdf0e10cSrcweir     {
129cdf0e10cSrcweir         throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM(
130cdf0e10cSrcweir             "python global interpreter must be held (thread must be attached)" )),
131cdf0e10cSrcweir                                 Reference< XInterface > () );
132cdf0e10cSrcweir     }
133cdf0e10cSrcweir 
134cdf0e10cSrcweir     globalDict = PyRef( PyModule_GetDict(PyImport_AddModule(const_cast< char * >("__main__"))));
135cdf0e10cSrcweir 
136cdf0e10cSrcweir     if( ! globalDict.is() ) // FATAL !
137cdf0e10cSrcweir     {
138cdf0e10cSrcweir         throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM(
139cdf0e10cSrcweir             "can't find __main__ module" )), Reference< XInterface > ());
140cdf0e10cSrcweir     }
141cdf0e10cSrcweir     runtimeImpl = PyDict_GetItemString( globalDict.get() , "pyuno_runtime" );
142cdf0e10cSrcweir }
143cdf0e10cSrcweir 
144cdf0e10cSrcweir static PyRef importUnoModule( ) throw ( RuntimeException )
145cdf0e10cSrcweir {
146cdf0e10cSrcweir     PyRef globalDict = PyRef( PyModule_GetDict(PyImport_AddModule(const_cast< char * >("__main__"))));
147cdf0e10cSrcweir     // import the uno module
148cdf0e10cSrcweir     PyRef module( PyImport_ImportModule( const_cast< char * >("uno") ), SAL_NO_ACQUIRE );
149cdf0e10cSrcweir     if( PyErr_Occurred() )
150cdf0e10cSrcweir     {
151cdf0e10cSrcweir         PyRef excType, excValue, excTraceback;
152cdf0e10cSrcweir         PyErr_Fetch( (PyObject **)&excType, (PyObject**)&excValue,(PyObject**)&excTraceback);
153cdf0e10cSrcweir         PyRef str( PyObject_Repr( excTraceback.get() ), SAL_NO_ACQUIRE );
154cdf0e10cSrcweir 
155cdf0e10cSrcweir         OUStringBuffer buf;
156cdf0e10cSrcweir         buf.appendAscii( "python object raised an unknown exception (" );
157cdf0e10cSrcweir         PyRef valueRep( PyObject_Repr( excValue.get() ), SAL_NO_ACQUIRE );
158cdf0e10cSrcweir         buf.appendAscii( PyString_AsString( valueRep.get())).appendAscii( ", traceback follows\n" );
159cdf0e10cSrcweir         buf.appendAscii( PyString_AsString( str.get() ) );
160cdf0e10cSrcweir         throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface > () );
161cdf0e10cSrcweir     }
162cdf0e10cSrcweir     PyRef dict( PyModule_GetDict( module.get() ) );
163cdf0e10cSrcweir     return dict;
164cdf0e10cSrcweir }
165cdf0e10cSrcweir 
166cdf0e10cSrcweir static void readLoggingConfig( sal_Int32 *pLevel, FILE **ppFile )
167cdf0e10cSrcweir {
168cdf0e10cSrcweir     *pLevel = LogLevel::NONE;
169cdf0e10cSrcweir     *ppFile = 0;
170cdf0e10cSrcweir     OUString fileName;
171cdf0e10cSrcweir     osl_getModuleURLFromFunctionAddress(
172cdf0e10cSrcweir         reinterpret_cast< oslGenericFunction >(readLoggingConfig),
173cdf0e10cSrcweir         (rtl_uString **) &fileName );
174cdf0e10cSrcweir     fileName = OUString( fileName.getStr(), fileName.lastIndexOf( '/' )+1 );
175cdf0e10cSrcweir     fileName += OUString::createFromAscii(  SAL_CONFIGFILE("pyuno") );
176cdf0e10cSrcweir     rtl::Bootstrap bootstrapHandle( fileName );
177cdf0e10cSrcweir 
178cdf0e10cSrcweir     OUString str;
179cdf0e10cSrcweir     if( bootstrapHandle.getFrom( USTR_ASCII( "PYUNO_LOGLEVEL" ), str ) )
180cdf0e10cSrcweir     {
181cdf0e10cSrcweir         if( str.equalsAscii( "NONE" ) )
182cdf0e10cSrcweir             *pLevel = LogLevel::NONE;
183cdf0e10cSrcweir         else if( str.equalsAscii( "CALL" ) )
184cdf0e10cSrcweir             *pLevel = LogLevel::CALL;
185cdf0e10cSrcweir         else if( str.equalsAscii( "ARGS" ) )
186cdf0e10cSrcweir             *pLevel = LogLevel::ARGS;
187cdf0e10cSrcweir         else
188cdf0e10cSrcweir         {
189cdf0e10cSrcweir             fprintf( stderr, "unknown loglevel %s\n",
190cdf0e10cSrcweir                      OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
191cdf0e10cSrcweir         }
192cdf0e10cSrcweir     }
193cdf0e10cSrcweir     if( *pLevel > LogLevel::NONE )
194cdf0e10cSrcweir     {
195cdf0e10cSrcweir         *ppFile = stdout;
196cdf0e10cSrcweir         if( bootstrapHandle.getFrom( USTR_ASCII( "PYUNO_LOGTARGET" ), str ) )
197cdf0e10cSrcweir         {
198cdf0e10cSrcweir             if( str.equalsAscii( "stdout" ) )
199cdf0e10cSrcweir                 *ppFile = stdout;
200cdf0e10cSrcweir             else if( str.equalsAscii( "stderr" ) )
201cdf0e10cSrcweir                 *ppFile = stderr;
202cdf0e10cSrcweir             else
203cdf0e10cSrcweir             {
204cdf0e10cSrcweir                 oslProcessInfo data;
205cdf0e10cSrcweir                 data.Size = sizeof( data );
206cdf0e10cSrcweir                 osl_getProcessInfo(
207cdf0e10cSrcweir                     0 , osl_Process_IDENTIFIER , &data );
208cdf0e10cSrcweir                 osl_getSystemPathFromFileURL( str.pData, &str.pData);
209cdf0e10cSrcweir                 OString o = OUStringToOString( str, osl_getThreadTextEncoding() );
210cdf0e10cSrcweir                 o += ".";
211cdf0e10cSrcweir                 o += OString::valueOf( (sal_Int32)data.Ident );
212cdf0e10cSrcweir 
213cdf0e10cSrcweir                 *ppFile = fopen( o.getStr() , "w" );
214cdf0e10cSrcweir                 if ( *ppFile )
215cdf0e10cSrcweir                 {
216cdf0e10cSrcweir                     // do not buffer (useful if e.g. analyzing a crash)
217cdf0e10cSrcweir                     setvbuf( *ppFile, 0, _IONBF, 0 );
218cdf0e10cSrcweir                 }
219cdf0e10cSrcweir                 else
220cdf0e10cSrcweir                 {
221cdf0e10cSrcweir                     fprintf( stderr, "couldn't create file %s\n",
222cdf0e10cSrcweir                              OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
223cdf0e10cSrcweir 
224cdf0e10cSrcweir                 }
225cdf0e10cSrcweir             }
226cdf0e10cSrcweir         }
227cdf0e10cSrcweir     }
228cdf0e10cSrcweir }
229cdf0e10cSrcweir 
230cdf0e10cSrcweir /*-------------------------------------------------------------------
231cdf0e10cSrcweir  RuntimeImpl implementations
232cdf0e10cSrcweir  *-------------------------------------------------------------------*/
233cdf0e10cSrcweir PyRef stRuntimeImpl::create( const Reference< XComponentContext > &ctx )
234cdf0e10cSrcweir     throw( com::sun::star::uno::RuntimeException )
235cdf0e10cSrcweir {
236cdf0e10cSrcweir     RuntimeImpl *me = PyObject_New (RuntimeImpl, &RuntimeImpl_Type);
237cdf0e10cSrcweir     if( ! me )
238cdf0e10cSrcweir         throw RuntimeException(
239cdf0e10cSrcweir             OUString( RTL_CONSTASCII_USTRINGPARAM( "cannot instantiate pyuno::RuntimeImpl" ) ),
240cdf0e10cSrcweir             Reference< XInterface > () );
241cdf0e10cSrcweir     me->cargo = 0;
242cdf0e10cSrcweir     // must use a different struct here, as the PyObject_New
243cdf0e10cSrcweir     // makes C++ unusable
244cdf0e10cSrcweir     RuntimeCargo *c = new RuntimeCargo();
245cdf0e10cSrcweir     readLoggingConfig( &(c->logLevel) , &(c->logFile) );
246cdf0e10cSrcweir     log( c, LogLevel::CALL, "Instantiating pyuno bridge" );
247cdf0e10cSrcweir 
248cdf0e10cSrcweir     c->valid = 1;
249cdf0e10cSrcweir     c->xContext = ctx;
250cdf0e10cSrcweir     c->xInvocation = Reference< XSingleServiceFactory > (
251cdf0e10cSrcweir         ctx->getServiceManager()->createInstanceWithContext(
252cdf0e10cSrcweir             OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.script.Invocation" ) ),
253cdf0e10cSrcweir             ctx ),
254cdf0e10cSrcweir         UNO_QUERY );
255cdf0e10cSrcweir     if( ! c->xInvocation.is() )
256cdf0e10cSrcweir         throw RuntimeException(
257cdf0e10cSrcweir             OUString( RTL_CONSTASCII_USTRINGPARAM( "pyuno: couldn't instantiate invocation service" ) ),
258cdf0e10cSrcweir             Reference< XInterface > () );
259cdf0e10cSrcweir 
260cdf0e10cSrcweir     c->xTypeConverter = Reference< XTypeConverter > (
261cdf0e10cSrcweir         ctx->getServiceManager()->createInstanceWithContext(
262cdf0e10cSrcweir             OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.script.Converter" ) ),
263cdf0e10cSrcweir             ctx ),
264cdf0e10cSrcweir         UNO_QUERY );
265cdf0e10cSrcweir     if( ! c->xTypeConverter.is() )
266cdf0e10cSrcweir         throw RuntimeException(
267cdf0e10cSrcweir             OUString( RTL_CONSTASCII_USTRINGPARAM( "pyuno: couldn't instantiate typeconverter service" )),
268cdf0e10cSrcweir             Reference< XInterface > () );
269cdf0e10cSrcweir 
270cdf0e10cSrcweir     c->xCoreReflection = Reference< XIdlReflection > (
271cdf0e10cSrcweir         ctx->getServiceManager()->createInstanceWithContext(
272cdf0e10cSrcweir             OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.reflection.CoreReflection" ) ),
273cdf0e10cSrcweir             ctx ),
274cdf0e10cSrcweir         UNO_QUERY );
275cdf0e10cSrcweir     if( ! c->xCoreReflection.is() )
276cdf0e10cSrcweir         throw RuntimeException(
277cdf0e10cSrcweir             OUString( RTL_CONSTASCII_USTRINGPARAM( "pyuno: couldn't instantiate corereflection service" )),
278cdf0e10cSrcweir             Reference< XInterface > () );
279cdf0e10cSrcweir 
280cdf0e10cSrcweir     c->xAdapterFactory = Reference< XInvocationAdapterFactory2 > (
281cdf0e10cSrcweir         ctx->getServiceManager()->createInstanceWithContext(
282cdf0e10cSrcweir             OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.script.InvocationAdapterFactory" ) ),
283cdf0e10cSrcweir             ctx ),
284cdf0e10cSrcweir         UNO_QUERY );
285cdf0e10cSrcweir     if( ! c->xAdapterFactory.is() )
286cdf0e10cSrcweir         throw RuntimeException(
287cdf0e10cSrcweir             OUString( RTL_CONSTASCII_USTRINGPARAM( "pyuno: couldn't instantiate invocation adapter factory service" )),
288cdf0e10cSrcweir             Reference< XInterface > () );
289cdf0e10cSrcweir 
290cdf0e10cSrcweir     c->xIntrospection = Reference< XIntrospection > (
291cdf0e10cSrcweir         ctx->getServiceManager()->createInstanceWithContext(
292cdf0e10cSrcweir             OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.beans.Introspection" ) ),
293cdf0e10cSrcweir             ctx ),
294cdf0e10cSrcweir         UNO_QUERY );
295cdf0e10cSrcweir     if( ! c->xIntrospection.is() )
296cdf0e10cSrcweir         throw RuntimeException(
297cdf0e10cSrcweir             OUString( RTL_CONSTASCII_USTRINGPARAM( "pyuno: couldn't instantiate introspection service" )),
298cdf0e10cSrcweir             Reference< XInterface > () );
299cdf0e10cSrcweir 
300cdf0e10cSrcweir     Any a = ctx->getValueByName(OUString(
301cdf0e10cSrcweir         RTL_CONSTASCII_USTRINGPARAM("/singletons/com.sun.star.reflection.theTypeDescriptionManager" )) );
302cdf0e10cSrcweir     a >>= c->xTdMgr;
303cdf0e10cSrcweir     if( ! c->xTdMgr.is() )
304cdf0e10cSrcweir         throw RuntimeException(
305cdf0e10cSrcweir             OUString( RTL_CONSTASCII_USTRINGPARAM( "pyuno: couldn't retrieve typedescriptionmanager" )),
306cdf0e10cSrcweir             Reference< XInterface > () );
307cdf0e10cSrcweir 
308cdf0e10cSrcweir     me->cargo =c;
309cdf0e10cSrcweir     return PyRef( reinterpret_cast< PyObject * > ( me ), SAL_NO_ACQUIRE );
310cdf0e10cSrcweir }
311cdf0e10cSrcweir 
312cdf0e10cSrcweir void  stRuntimeImpl::del(PyObject* self)
313cdf0e10cSrcweir {
314cdf0e10cSrcweir     RuntimeImpl *me = reinterpret_cast< RuntimeImpl * > ( self );
315cdf0e10cSrcweir     if( me->cargo->logFile )
316cdf0e10cSrcweir         fclose( me->cargo->logFile );
317cdf0e10cSrcweir     delete me->cargo;
318cdf0e10cSrcweir     PyObject_Del (self);
319cdf0e10cSrcweir }
320cdf0e10cSrcweir 
321cdf0e10cSrcweir 
322cdf0e10cSrcweir void Runtime::initialize( const Reference< XComponentContext > & ctx )
323cdf0e10cSrcweir     throw ( RuntimeException )
324cdf0e10cSrcweir {
325cdf0e10cSrcweir     PyRef globalDict, runtime;
326cdf0e10cSrcweir     getRuntimeImpl( globalDict , runtime );
327cdf0e10cSrcweir     RuntimeImpl *impl = reinterpret_cast< RuntimeImpl * > (runtime.get());
328cdf0e10cSrcweir 
329cdf0e10cSrcweir     if( runtime.is() && impl->cargo->valid )
330cdf0e10cSrcweir     {
331cdf0e10cSrcweir         throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM(
332cdf0e10cSrcweir             "pyuno runtime has already been initialized before" ) ),
333cdf0e10cSrcweir                                 Reference< XInterface > () );
334cdf0e10cSrcweir     }
335cdf0e10cSrcweir     PyRef keep( RuntimeImpl::create( ctx ) );
336cdf0e10cSrcweir     PyDict_SetItemString( globalDict.get(), "pyuno_runtime" , keep.get() );
337cdf0e10cSrcweir     Py_XINCREF( keep.get() );
338cdf0e10cSrcweir }
339cdf0e10cSrcweir 
340cdf0e10cSrcweir 
341cdf0e10cSrcweir bool Runtime::isInitialized() throw ( RuntimeException )
342cdf0e10cSrcweir {
343cdf0e10cSrcweir     PyRef globalDict, runtime;
344cdf0e10cSrcweir     getRuntimeImpl( globalDict , runtime );
345cdf0e10cSrcweir     RuntimeImpl *impl = reinterpret_cast< RuntimeImpl * > (runtime.get());
346cdf0e10cSrcweir     return runtime.is() && impl->cargo->valid;
347cdf0e10cSrcweir }
348cdf0e10cSrcweir 
349cdf0e10cSrcweir void Runtime::finalize() throw (RuntimeException)
350cdf0e10cSrcweir {
351cdf0e10cSrcweir     PyRef globalDict, runtime;
352cdf0e10cSrcweir     getRuntimeImpl( globalDict , runtime );
353cdf0e10cSrcweir     RuntimeImpl *impl = reinterpret_cast< RuntimeImpl * > (runtime.get());
354cdf0e10cSrcweir     if( !runtime.is() || ! impl->cargo->valid )
355cdf0e10cSrcweir     {
356cdf0e10cSrcweir         throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM(
357cdf0e10cSrcweir             "pyuno bridge must have been initialized before finalizing" )),
358cdf0e10cSrcweir                                 Reference< XInterface > () );
359cdf0e10cSrcweir     }
360cdf0e10cSrcweir     impl->cargo->valid = false;
361cdf0e10cSrcweir     impl->cargo->xInvocation.clear();
362cdf0e10cSrcweir     impl->cargo->xContext.clear();
363cdf0e10cSrcweir     impl->cargo->xTypeConverter.clear();
364cdf0e10cSrcweir }
365cdf0e10cSrcweir 
366cdf0e10cSrcweir Runtime::Runtime() throw(  RuntimeException )
367cdf0e10cSrcweir     : impl( 0 )
368cdf0e10cSrcweir {
369cdf0e10cSrcweir     PyRef globalDict, runtime;
370cdf0e10cSrcweir     getRuntimeImpl( globalDict , runtime );
371cdf0e10cSrcweir     if( ! runtime.is() )
372cdf0e10cSrcweir     {
373cdf0e10cSrcweir         throw RuntimeException(
374cdf0e10cSrcweir             OUString( RTL_CONSTASCII_USTRINGPARAM("pyuno runtime is not initialized, "
375cdf0e10cSrcweir                                                   "(the pyuno.bootstrap needs to be called before using any uno classes)")),
376cdf0e10cSrcweir             Reference< XInterface > () );
377cdf0e10cSrcweir     }
378cdf0e10cSrcweir     impl = reinterpret_cast< RuntimeImpl * > (runtime.get());
379cdf0e10cSrcweir     Py_XINCREF( runtime.get() );
380cdf0e10cSrcweir }
381cdf0e10cSrcweir 
382cdf0e10cSrcweir Runtime::Runtime( const Runtime & r )
383cdf0e10cSrcweir {
384cdf0e10cSrcweir     impl = r.impl;
385cdf0e10cSrcweir     Py_XINCREF( reinterpret_cast< PyObject * >(impl) );
386cdf0e10cSrcweir }
387cdf0e10cSrcweir 
388cdf0e10cSrcweir Runtime::~Runtime()
389cdf0e10cSrcweir {
390cdf0e10cSrcweir     Py_XDECREF( reinterpret_cast< PyObject * >(impl) );
391cdf0e10cSrcweir }
392cdf0e10cSrcweir 
393cdf0e10cSrcweir Runtime & Runtime::operator = ( const Runtime & r )
394cdf0e10cSrcweir {
395cdf0e10cSrcweir     PyRef temp( reinterpret_cast< PyObject * >(r.impl) );
396cdf0e10cSrcweir     Py_XINCREF( temp.get() );
397cdf0e10cSrcweir     Py_XDECREF( reinterpret_cast< PyObject * >(impl) );
398cdf0e10cSrcweir     impl = r.impl;
399cdf0e10cSrcweir     return *this;
400cdf0e10cSrcweir }
401cdf0e10cSrcweir 
402cdf0e10cSrcweir PyRef Runtime::any2PyObject (const Any &a ) const
403cdf0e10cSrcweir     throw ( com::sun::star::script::CannotConvertException,
404cdf0e10cSrcweir             com::sun::star::lang::IllegalArgumentException,
405cdf0e10cSrcweir             RuntimeException)
406cdf0e10cSrcweir {
407cdf0e10cSrcweir     if( ! impl->cargo->valid )
408cdf0e10cSrcweir     {
409cdf0e10cSrcweir         throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM(
410cdf0e10cSrcweir             "pyuno runtime must be initialized before calling any2PyObject" )),
411cdf0e10cSrcweir                                 Reference< XInterface > () );
412cdf0e10cSrcweir     }
413cdf0e10cSrcweir 
414cdf0e10cSrcweir     switch (a.getValueTypeClass ())
415cdf0e10cSrcweir     {
416cdf0e10cSrcweir     case typelib_TypeClass_VOID:
417cdf0e10cSrcweir 	{
418cdf0e10cSrcweir         Py_INCREF (Py_None);
419cdf0e10cSrcweir         return PyRef(Py_None);
420cdf0e10cSrcweir 	}
421cdf0e10cSrcweir     case typelib_TypeClass_CHAR:
422cdf0e10cSrcweir 	{
423cdf0e10cSrcweir         sal_Unicode c = *(sal_Unicode*)a.getValue();
424cdf0e10cSrcweir         return PyRef( PyUNO_char_new( c , *this ), SAL_NO_ACQUIRE );
425cdf0e10cSrcweir 	}
426cdf0e10cSrcweir     case typelib_TypeClass_BOOLEAN:
427cdf0e10cSrcweir 	{
428cdf0e10cSrcweir         sal_Bool b = sal_Bool();
429cdf0e10cSrcweir         if ((a >>= b) && b)
430cdf0e10cSrcweir             return Py_True;
431cdf0e10cSrcweir         else
432cdf0e10cSrcweir             return Py_False;
433cdf0e10cSrcweir 	}
434cdf0e10cSrcweir     case typelib_TypeClass_BYTE:
435cdf0e10cSrcweir     case typelib_TypeClass_SHORT:
436cdf0e10cSrcweir     case typelib_TypeClass_UNSIGNED_SHORT:
437cdf0e10cSrcweir     case typelib_TypeClass_LONG:
438cdf0e10cSrcweir 	{
439cdf0e10cSrcweir         sal_Int32 l = 0;
440cdf0e10cSrcweir         a >>= l;
441cdf0e10cSrcweir         return PyRef( PyInt_FromLong (l), SAL_NO_ACQUIRE );
442cdf0e10cSrcweir 	}
443cdf0e10cSrcweir     case typelib_TypeClass_UNSIGNED_LONG:
444cdf0e10cSrcweir 	{
445cdf0e10cSrcweir         sal_uInt32 l = 0;
446cdf0e10cSrcweir         a >>= l;
447cdf0e10cSrcweir         return PyRef( PyLong_FromUnsignedLong (l), SAL_NO_ACQUIRE );
448cdf0e10cSrcweir 	}
449cdf0e10cSrcweir     case typelib_TypeClass_HYPER:
450cdf0e10cSrcweir 	{
451cdf0e10cSrcweir         sal_Int64 l = 0;
452cdf0e10cSrcweir         a >>= l;
453cdf0e10cSrcweir         return PyRef( PyLong_FromLongLong (l), SAL_NO_ACQUIRE);
454cdf0e10cSrcweir 	}
455cdf0e10cSrcweir     case typelib_TypeClass_UNSIGNED_HYPER:
456cdf0e10cSrcweir 	{
457cdf0e10cSrcweir         sal_uInt64 l = 0;
458cdf0e10cSrcweir         a >>= l;
459cdf0e10cSrcweir         return PyRef( PyLong_FromUnsignedLongLong (l), SAL_NO_ACQUIRE);
460cdf0e10cSrcweir 	}
461cdf0e10cSrcweir     case typelib_TypeClass_FLOAT:
462cdf0e10cSrcweir 	{
463cdf0e10cSrcweir         float f = 0.0;
464cdf0e10cSrcweir         a >>= f;
465cdf0e10cSrcweir         return PyRef(PyFloat_FromDouble (f), SAL_NO_ACQUIRE);
466cdf0e10cSrcweir 	}
467cdf0e10cSrcweir     case typelib_TypeClass_DOUBLE:
468cdf0e10cSrcweir 	{
469cdf0e10cSrcweir         double d = 0.0;
470cdf0e10cSrcweir         a >>= d;
471cdf0e10cSrcweir         return PyRef( PyFloat_FromDouble (d), SAL_NO_ACQUIRE);
472cdf0e10cSrcweir 	}
473cdf0e10cSrcweir     case typelib_TypeClass_STRING:
474cdf0e10cSrcweir 	{
475cdf0e10cSrcweir         OUString tmp_ostr;
476cdf0e10cSrcweir         a >>= tmp_ostr;
477cdf0e10cSrcweir         return ustring2PyUnicode( tmp_ostr );
478cdf0e10cSrcweir 	}
479cdf0e10cSrcweir     case typelib_TypeClass_TYPE:
480cdf0e10cSrcweir 	{
481cdf0e10cSrcweir         Type t;
482cdf0e10cSrcweir         a >>= t;
483cdf0e10cSrcweir         OString o = OUStringToOString( t.getTypeName(), RTL_TEXTENCODING_ASCII_US );
484cdf0e10cSrcweir         return PyRef(
485cdf0e10cSrcweir             PyUNO_Type_new (
486cdf0e10cSrcweir                 o.getStr(),  (com::sun::star::uno::TypeClass)t.getTypeClass(), *this),
487cdf0e10cSrcweir             SAL_NO_ACQUIRE);
488cdf0e10cSrcweir 	}
489cdf0e10cSrcweir     case typelib_TypeClass_ANY:
490cdf0e10cSrcweir 	{
491cdf0e10cSrcweir         //I don't think this can happen.
492cdf0e10cSrcweir         Py_INCREF (Py_None);
493cdf0e10cSrcweir         return Py_None;
494cdf0e10cSrcweir 	}
495cdf0e10cSrcweir     case typelib_TypeClass_ENUM:
496cdf0e10cSrcweir 	{
497cdf0e10cSrcweir         sal_Int32 l = *(sal_Int32 *) a.getValue();
498cdf0e10cSrcweir         TypeDescription desc( a.getValueType() );
499cdf0e10cSrcweir         if( desc.is() )
500cdf0e10cSrcweir         {
501cdf0e10cSrcweir             desc.makeComplete();
502cdf0e10cSrcweir             typelib_EnumTypeDescription *pEnumDesc =
503cdf0e10cSrcweir                 (typelib_EnumTypeDescription *) desc.get();
504cdf0e10cSrcweir             for( int i = 0 ; i < pEnumDesc->nEnumValues ; i ++ )
505cdf0e10cSrcweir             {
506cdf0e10cSrcweir                 if( pEnumDesc->pEnumValues[i] == l )
507cdf0e10cSrcweir                 {
508cdf0e10cSrcweir                     OString v = OUStringToOString( pEnumDesc->ppEnumNames[i], RTL_TEXTENCODING_ASCII_US);
509cdf0e10cSrcweir                     OString e = OUStringToOString( pEnumDesc->aBase.pTypeName, RTL_TEXTENCODING_ASCII_US);
510cdf0e10cSrcweir                     return PyRef( PyUNO_Enum_new(e.getStr(),v.getStr(), *this ), SAL_NO_ACQUIRE );
511cdf0e10cSrcweir                 }
512cdf0e10cSrcweir             }
513cdf0e10cSrcweir         }
514cdf0e10cSrcweir         OUStringBuffer buf;
515cdf0e10cSrcweir         buf.appendAscii( "Any carries enum " );
516cdf0e10cSrcweir         buf.append( a.getValueType().getTypeName());
517cdf0e10cSrcweir         buf.appendAscii( " with invalid value " ).append( l );
518cdf0e10cSrcweir         throw RuntimeException( buf.makeStringAndClear() , Reference< XInterface > ()  );
519cdf0e10cSrcweir 	}
520cdf0e10cSrcweir     case typelib_TypeClass_EXCEPTION:
521cdf0e10cSrcweir     case typelib_TypeClass_STRUCT:
522cdf0e10cSrcweir     {
523cdf0e10cSrcweir         PyRef excClass = getClass( a.getValueType().getTypeName(), *this );
524cdf0e10cSrcweir         PyRef value = PyRef( PyUNO_new_UNCHECKED (a, getImpl()->cargo->xInvocation), SAL_NO_ACQUIRE);
525cdf0e10cSrcweir         PyRef argsTuple( PyTuple_New( 1 ) , SAL_NO_ACQUIRE );
526cdf0e10cSrcweir         PyTuple_SetItem( argsTuple.get() , 0 , value.getAcquired() );
527cdf0e10cSrcweir         PyRef ret( PyObject_CallObject( excClass.get() , argsTuple.get() ), SAL_NO_ACQUIRE );
528cdf0e10cSrcweir         if( ! ret.is() )
529cdf0e10cSrcweir         {
530cdf0e10cSrcweir             OUStringBuffer buf;
531cdf0e10cSrcweir             buf.appendAscii( "Couldn't instantiate python representation of structered UNO type " );
532cdf0e10cSrcweir             buf.append( a.getValueType().getTypeName() );
533cdf0e10cSrcweir             throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface > () );
534cdf0e10cSrcweir         }
535cdf0e10cSrcweir 
536cdf0e10cSrcweir         if( com::sun::star::uno::TypeClass_EXCEPTION == a.getValueTypeClass() )
537cdf0e10cSrcweir         {
538cdf0e10cSrcweir             // add the message in a standard python way !
539cdf0e10cSrcweir             PyRef args( PyTuple_New( 1 ), SAL_NO_ACQUIRE );
540cdf0e10cSrcweir 
541cdf0e10cSrcweir             // assuming that the Message is always the first member, wuuuu
542cdf0e10cSrcweir             void *pData = (void*)a.getValue();
543cdf0e10cSrcweir             OUString message = *(OUString * )pData;
544cdf0e10cSrcweir             PyRef pymsg = ustring2PyString( message );
545cdf0e10cSrcweir             PyTuple_SetItem( args.get(), 0 , pymsg.getAcquired() );
546cdf0e10cSrcweir             // the exception base functions want to have an "args" tuple,
547cdf0e10cSrcweir             // which contains the message
548cdf0e10cSrcweir             PyObject_SetAttrString( ret.get(), const_cast< char * >("args"), args.get() );
549cdf0e10cSrcweir         }
550cdf0e10cSrcweir         return ret;
551cdf0e10cSrcweir     }
552cdf0e10cSrcweir     case typelib_TypeClass_SEQUENCE:
553cdf0e10cSrcweir 	{
554cdf0e10cSrcweir         Sequence<Any> s;
555cdf0e10cSrcweir 
556cdf0e10cSrcweir         Sequence< sal_Int8 > byteSequence;
557cdf0e10cSrcweir         if( a >>= byteSequence )
558cdf0e10cSrcweir         {
559cdf0e10cSrcweir             // byte sequence is treated in a special way because of peformance reasons
560cdf0e10cSrcweir             // @since 0.9.2
561cdf0e10cSrcweir             return PyRef( PyUNO_ByteSequence_new( byteSequence, *this ), SAL_NO_ACQUIRE );
562cdf0e10cSrcweir         }
563cdf0e10cSrcweir         else
564cdf0e10cSrcweir         {
565cdf0e10cSrcweir             Reference< XTypeConverter > tc = getImpl()->cargo->xTypeConverter;
566cdf0e10cSrcweir             Reference< XSingleServiceFactory > ssf = getImpl()->cargo->xInvocation;
567cdf0e10cSrcweir             tc->convertTo (a, ::getCppuType (&s)) >>= s;
568cdf0e10cSrcweir             PyRef tuple( PyTuple_New (s.getLength()), SAL_NO_ACQUIRE);
569cdf0e10cSrcweir             int i=0;
570cdf0e10cSrcweir             OUString errMsg;
571cdf0e10cSrcweir             try
572cdf0e10cSrcweir             {
573cdf0e10cSrcweir                 for ( i = 0; i < s.getLength (); i++)
574cdf0e10cSrcweir                 {
575cdf0e10cSrcweir                     PyRef element;
576cdf0e10cSrcweir                     element = any2PyObject (tc->convertTo (s[i], s[i].getValueType() ));
577cdf0e10cSrcweir                     OSL_ASSERT( element.is() );
578cdf0e10cSrcweir                     PyTuple_SetItem( tuple.get(), i, element.getAcquired() );
579cdf0e10cSrcweir                 }
580cdf0e10cSrcweir             }
581cdf0e10cSrcweir             catch( com::sun::star::uno::Exception & )
582cdf0e10cSrcweir             {
583cdf0e10cSrcweir                 for( ; i < s.getLength() ; i ++ )
584cdf0e10cSrcweir                 {
585cdf0e10cSrcweir                     Py_INCREF( Py_None );
586cdf0e10cSrcweir                     PyTuple_SetItem( tuple.get(), i,  Py_None );
587cdf0e10cSrcweir                 }
588cdf0e10cSrcweir                 throw;
589cdf0e10cSrcweir             }
590cdf0e10cSrcweir             return tuple;
591cdf0e10cSrcweir 	    }
592cdf0e10cSrcweir 	}
593cdf0e10cSrcweir     case typelib_TypeClass_INTERFACE:
594cdf0e10cSrcweir 	{
595cdf0e10cSrcweir         Reference< XUnoTunnel > tunnel;
596cdf0e10cSrcweir         a >>= tunnel;
597cdf0e10cSrcweir         if( tunnel.is() )
598cdf0e10cSrcweir         {
599cdf0e10cSrcweir             sal_Int64 that = tunnel->getSomething( ::pyuno::Adapter::getUnoTunnelImplementationId() );
600cdf0e10cSrcweir             if( that )
601cdf0e10cSrcweir                 return ((Adapter*)sal::static_int_cast< sal_IntPtr >(that))->getWrappedObject();
602cdf0e10cSrcweir         }
603cdf0e10cSrcweir         //This is just like the struct case:
604cdf0e10cSrcweir         return PyRef( PyUNO_new (a, getImpl()->cargo->xInvocation), SAL_NO_ACQUIRE );
605cdf0e10cSrcweir 	}
606cdf0e10cSrcweir     default:
607cdf0e10cSrcweir 	{
608cdf0e10cSrcweir         OUStringBuffer buf;
609cdf0e10cSrcweir         buf.appendAscii( "Unknonwn UNO type class " );
610cdf0e10cSrcweir         buf.append( (sal_Int32 ) a.getValueTypeClass() );
611cdf0e10cSrcweir         throw RuntimeException(buf.makeStringAndClear( ), Reference< XInterface > () );
612cdf0e10cSrcweir 	}
613cdf0e10cSrcweir     }
614cdf0e10cSrcweir     //We shouldn't be here...
615cdf0e10cSrcweir     Py_INCREF( Py_None );
616cdf0e10cSrcweir     return Py_None;
617cdf0e10cSrcweir }
618cdf0e10cSrcweir 
619cdf0e10cSrcweir static Sequence< Type > invokeGetTypes( const Runtime & r , PyObject * o )
620cdf0e10cSrcweir {
621cdf0e10cSrcweir     Sequence< Type > ret;
622cdf0e10cSrcweir 
623cdf0e10cSrcweir     PyRef method( PyObject_GetAttrString( o , const_cast< char * >("getTypes") ), SAL_NO_ACQUIRE );
624cdf0e10cSrcweir     raiseInvocationTargetExceptionWhenNeeded( r );
625cdf0e10cSrcweir     if( method.is() && PyCallable_Check( method.get() ) )
626cdf0e10cSrcweir     {
627cdf0e10cSrcweir         PyRef types( PyObject_CallObject( method.get(), 0 ) , SAL_NO_ACQUIRE );
628cdf0e10cSrcweir         raiseInvocationTargetExceptionWhenNeeded( r );
629cdf0e10cSrcweir         if( types.is() && PyTuple_Check( types.get() ) )
630cdf0e10cSrcweir         {
631cdf0e10cSrcweir             int size = PyTuple_Size( types.get() );
632cdf0e10cSrcweir 
633cdf0e10cSrcweir             // add the XUnoTunnel interface  for uno object identity concept (hack)
634cdf0e10cSrcweir             ret.realloc( size + 1 );
635cdf0e10cSrcweir             for( int i = 0 ; i < size ; i ++ )
636cdf0e10cSrcweir             {
637cdf0e10cSrcweir                 Any a = r.pyObject2Any(PyTuple_GetItem(types.get(),i));
638cdf0e10cSrcweir                 a >>= ret[i];
639cdf0e10cSrcweir             }
640cdf0e10cSrcweir             ret[size] = getCppuType( (Reference< com::sun::star::lang::XUnoTunnel> *) 0 );
641cdf0e10cSrcweir         }
642cdf0e10cSrcweir     }
643cdf0e10cSrcweir     return ret;
644cdf0e10cSrcweir }
645cdf0e10cSrcweir 
646cdf0e10cSrcweir Any Runtime::pyObject2Any ( const PyRef & source, enum ConversionMode mode ) const
647cdf0e10cSrcweir     throw ( com::sun::star::uno::RuntimeException )
648cdf0e10cSrcweir {
649cdf0e10cSrcweir     if( ! impl->cargo->valid )
650cdf0e10cSrcweir     {
651cdf0e10cSrcweir         throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM(
652cdf0e10cSrcweir             "pyuno runtime must be initialized before calling any2PyObject" )),
653cdf0e10cSrcweir                                 Reference< XInterface > () );
654cdf0e10cSrcweir     }
655cdf0e10cSrcweir 
656cdf0e10cSrcweir     Any a;
657cdf0e10cSrcweir     PyObject *o = source.get();
658cdf0e10cSrcweir     if( Py_None == o )
659cdf0e10cSrcweir     {
660cdf0e10cSrcweir 
661cdf0e10cSrcweir     }
662cdf0e10cSrcweir     else if (PyInt_Check (o))
663cdf0e10cSrcweir     {
664cdf0e10cSrcweir         if( o == Py_True )
665cdf0e10cSrcweir         {
666cdf0e10cSrcweir             sal_Bool b = sal_True;
667cdf0e10cSrcweir             a = Any( &b, getBooleanCppuType() );
668cdf0e10cSrcweir         }
669cdf0e10cSrcweir         else if ( o == Py_False )
670cdf0e10cSrcweir         {
671cdf0e10cSrcweir             sal_Bool b = sal_False;
672cdf0e10cSrcweir             a = Any( &b, getBooleanCppuType() );
673cdf0e10cSrcweir         }
674cdf0e10cSrcweir         else
675cdf0e10cSrcweir         {
676cdf0e10cSrcweir             sal_Int32 l = (sal_Int32) PyInt_AsLong( o );
677cdf0e10cSrcweir             if( l < 128 && l >= -128 )
678cdf0e10cSrcweir             {
679cdf0e10cSrcweir                 sal_Int8 b = (sal_Int8 ) l;
680cdf0e10cSrcweir                 a <<= b;
681cdf0e10cSrcweir             }
682cdf0e10cSrcweir             else if( l <= 0x7fff && l >= -0x8000 )
683cdf0e10cSrcweir             {
684cdf0e10cSrcweir                 sal_Int16 s = (sal_Int16) l;
685cdf0e10cSrcweir                 a <<= s;
686cdf0e10cSrcweir             }
687cdf0e10cSrcweir             else
688cdf0e10cSrcweir             {
689cdf0e10cSrcweir                 a <<= l;
690cdf0e10cSrcweir             }
691cdf0e10cSrcweir         }
692cdf0e10cSrcweir     }
693cdf0e10cSrcweir     else if (PyLong_Check (o))
694cdf0e10cSrcweir     {
695cdf0e10cSrcweir         sal_Int64 l = (sal_Int64)PyLong_AsLong (o);
696cdf0e10cSrcweir         if( l < 128 && l >= -128 )
697cdf0e10cSrcweir         {
698cdf0e10cSrcweir             sal_Int8 b = (sal_Int8 ) l;
699cdf0e10cSrcweir             a <<= b;
700cdf0e10cSrcweir         }
701cdf0e10cSrcweir         else if( l <= 0x7fff && l >= -0x8000 )
702cdf0e10cSrcweir         {
703cdf0e10cSrcweir             sal_Int16 s = (sal_Int16) l;
704cdf0e10cSrcweir             a <<= s;
705cdf0e10cSrcweir         }
706cdf0e10cSrcweir         else if( l <= SAL_CONST_INT64(0x7fffffff) &&
707cdf0e10cSrcweir                  l >= -SAL_CONST_INT64(0x80000000) )
708cdf0e10cSrcweir         {
709cdf0e10cSrcweir             sal_Int32 l32 = (sal_Int32) l;
710cdf0e10cSrcweir             a <<= l32;
711cdf0e10cSrcweir         }
712cdf0e10cSrcweir         else
713cdf0e10cSrcweir         {
714cdf0e10cSrcweir             a <<= l;
715cdf0e10cSrcweir         }
716cdf0e10cSrcweir     }
717cdf0e10cSrcweir     else if (PyFloat_Check (o))
718cdf0e10cSrcweir     {
719cdf0e10cSrcweir         double d = PyFloat_AsDouble (o);
720cdf0e10cSrcweir         a <<= d;
721cdf0e10cSrcweir     }
722cdf0e10cSrcweir     else if (PyString_Check (o))
723cdf0e10cSrcweir 	a <<= pyString2ustring(o);
724cdf0e10cSrcweir     else if( PyUnicode_Check( o ) )
725cdf0e10cSrcweir 	a <<= pyString2ustring(o);
726cdf0e10cSrcweir     else if (PyTuple_Check (o))
727cdf0e10cSrcweir     {
728cdf0e10cSrcweir         Sequence<Any> s (PyTuple_Size (o));
729cdf0e10cSrcweir         for (int i = 0; i < PyTuple_Size (o); i++)
730cdf0e10cSrcweir         {
731cdf0e10cSrcweir             s[i] = pyObject2Any (PyTuple_GetItem (o, i), mode );
732cdf0e10cSrcweir         }
733cdf0e10cSrcweir         a <<= s;
734cdf0e10cSrcweir     }
735cdf0e10cSrcweir     else
736cdf0e10cSrcweir     {
737cdf0e10cSrcweir         Runtime runtime;
738cdf0e10cSrcweir         // should be removed, in case ByteSequence gets derived from String
739cdf0e10cSrcweir         if( PyObject_IsInstance( o, getByteSequenceClass( runtime ).get() ) )
740cdf0e10cSrcweir         {
741cdf0e10cSrcweir             PyRef str(PyObject_GetAttrString( o , const_cast< char * >("value") ),SAL_NO_ACQUIRE);
742cdf0e10cSrcweir             Sequence< sal_Int8 > seq;
743cdf0e10cSrcweir             if( PyString_Check( str.get() ) )
744cdf0e10cSrcweir             {
745cdf0e10cSrcweir                 seq = Sequence<sal_Int8 > (
746cdf0e10cSrcweir                     (sal_Int8*) PyString_AsString(str.get()), PyString_Size(str.get()));
747cdf0e10cSrcweir             }
748cdf0e10cSrcweir             a <<= seq;
749cdf0e10cSrcweir         }
750cdf0e10cSrcweir         else
751cdf0e10cSrcweir         if( PyObject_IsInstance( o, getTypeClass( runtime ).get() ) )
752cdf0e10cSrcweir         {
753cdf0e10cSrcweir             Type t = PyType2Type( o );
754cdf0e10cSrcweir             a <<= t;
755cdf0e10cSrcweir         }
756cdf0e10cSrcweir         else if( PyObject_IsInstance( o, getEnumClass( runtime ).get() ) )
757cdf0e10cSrcweir         {
758cdf0e10cSrcweir             a = PyEnum2Enum( o );
759cdf0e10cSrcweir         }
760cdf0e10cSrcweir         else if( isInstanceOfStructOrException( o ) )
761cdf0e10cSrcweir         {
762cdf0e10cSrcweir             PyRef struc(PyObject_GetAttrString( o , const_cast< char * >("value") ),SAL_NO_ACQUIRE);
763cdf0e10cSrcweir             PyUNO * obj = (PyUNO*)struc.get();
764cdf0e10cSrcweir             Reference< XMaterialHolder > holder( obj->members->xInvocation, UNO_QUERY );
765cdf0e10cSrcweir             if( holder.is( ) )
766cdf0e10cSrcweir                 a = holder->getMaterial();
767cdf0e10cSrcweir             else
768cdf0e10cSrcweir             {
769cdf0e10cSrcweir                 throw RuntimeException(
770cdf0e10cSrcweir                     USTR_ASCII( "struct or exception wrapper does not support XMaterialHolder" ),
771cdf0e10cSrcweir                     Reference< XInterface > () );
772cdf0e10cSrcweir             }
773cdf0e10cSrcweir         }
774cdf0e10cSrcweir         else if( PyObject_IsInstance( o, getPyUnoClass( runtime ).get() ) )
775cdf0e10cSrcweir         {
776cdf0e10cSrcweir             PyUNO* o_pi;
777cdf0e10cSrcweir             o_pi = (PyUNO*) o;
778cdf0e10cSrcweir             if (o_pi->members->wrappedObject.getValueTypeClass () ==
779cdf0e10cSrcweir                 com::sun::star::uno::TypeClass_STRUCT ||
780cdf0e10cSrcweir                 o_pi->members->wrappedObject.getValueTypeClass () ==
781cdf0e10cSrcweir                 com::sun::star::uno::TypeClass_EXCEPTION)
782cdf0e10cSrcweir             {
783cdf0e10cSrcweir                 Reference<XMaterialHolder> my_mh (o_pi->members->xInvocation, UNO_QUERY);
784cdf0e10cSrcweir 
785cdf0e10cSrcweir                 if (!my_mh.is ())
786cdf0e10cSrcweir                 {
787cdf0e10cSrcweir                     throw RuntimeException(
788cdf0e10cSrcweir                         USTR_ASCII( "struct wrapper does not support XMaterialHolder" ),
789cdf0e10cSrcweir                         Reference< XInterface > () );
790cdf0e10cSrcweir                 }
791cdf0e10cSrcweir                 else
792cdf0e10cSrcweir                     a = my_mh->getMaterial ();
793cdf0e10cSrcweir             }
794cdf0e10cSrcweir             else
795cdf0e10cSrcweir             {
796cdf0e10cSrcweir                 a = o_pi->members->wrappedObject;
797cdf0e10cSrcweir             }
798cdf0e10cSrcweir         }
799cdf0e10cSrcweir         else if( PyObject_IsInstance( o, getCharClass( runtime ).get() ) )
800cdf0e10cSrcweir         {
801cdf0e10cSrcweir             sal_Unicode c = PyChar2Unicode( o );
802cdf0e10cSrcweir             a.setValue( &c, getCharCppuType( ));
803cdf0e10cSrcweir         }
804cdf0e10cSrcweir         else if( PyObject_IsInstance( o, getAnyClass( runtime ).get() ) )
805cdf0e10cSrcweir         {
806cdf0e10cSrcweir             if( ACCEPT_UNO_ANY == mode )
807cdf0e10cSrcweir             {
808cdf0e10cSrcweir                 a = pyObject2Any( PyRef( PyObject_GetAttrString( o , const_cast< char * >("value") ), SAL_NO_ACQUIRE) );
809cdf0e10cSrcweir                 Type t;
810cdf0e10cSrcweir                 pyObject2Any( PyRef( PyObject_GetAttrString( o, const_cast< char * >("type") ), SAL_NO_ACQUIRE ) ) >>= t;
811cdf0e10cSrcweir 
812cdf0e10cSrcweir                 try
813cdf0e10cSrcweir                 {
814cdf0e10cSrcweir                     a = getImpl()->cargo->xTypeConverter->convertTo( a, t );
815cdf0e10cSrcweir                 }
816cdf0e10cSrcweir                 catch( com::sun::star::uno::Exception & e )
817cdf0e10cSrcweir                 {
818cdf0e10cSrcweir                     throw RuntimeException( e.Message, e.Context );
819cdf0e10cSrcweir                 }
820cdf0e10cSrcweir             }
821cdf0e10cSrcweir             else
822cdf0e10cSrcweir             {
823cdf0e10cSrcweir                 throw RuntimeException(
824cdf0e10cSrcweir                     OUString( RTL_CONSTASCII_USTRINGPARAM(
825cdf0e10cSrcweir                                   "uno.Any instance not accepted during method call, "
826cdf0e10cSrcweir                                   "use uno.invoke instead" ) ),
827cdf0e10cSrcweir                     Reference< XInterface > () );
828cdf0e10cSrcweir             }
829cdf0e10cSrcweir         }
830cdf0e10cSrcweir         else
831cdf0e10cSrcweir         {
832cdf0e10cSrcweir             Reference< XInterface > mappedObject;
833cdf0e10cSrcweir             Reference< XInvocation > adapterObject;
834cdf0e10cSrcweir 
835cdf0e10cSrcweir             // instance already mapped out to the world ?
836cdf0e10cSrcweir             PyRef2Adapter::iterator ii = impl->cargo->mappedObjects.find( PyRef( o ) );
837cdf0e10cSrcweir             if( ii != impl->cargo->mappedObjects.end() )
838cdf0e10cSrcweir             {
839cdf0e10cSrcweir                 adapterObject = ii->second;
840cdf0e10cSrcweir             }
841cdf0e10cSrcweir 
842cdf0e10cSrcweir             if( adapterObject.is() )
843cdf0e10cSrcweir             {
844cdf0e10cSrcweir                 // object got already bridged !
845cdf0e10cSrcweir                 Reference< com::sun::star::lang::XUnoTunnel > tunnel( adapterObject, UNO_QUERY );
846cdf0e10cSrcweir 
847cdf0e10cSrcweir                 Adapter *pAdapter = ( Adapter * )
848cdf0e10cSrcweir                     sal::static_int_cast< sal_IntPtr >(
849cdf0e10cSrcweir                         tunnel->getSomething(
850cdf0e10cSrcweir                             ::pyuno::Adapter::getUnoTunnelImplementationId() ) );
851cdf0e10cSrcweir 
852cdf0e10cSrcweir                 mappedObject = impl->cargo->xAdapterFactory->createAdapter(
853cdf0e10cSrcweir                     adapterObject, pAdapter->getWrappedTypes() );
854cdf0e10cSrcweir             }
855cdf0e10cSrcweir             else
856cdf0e10cSrcweir             {
857cdf0e10cSrcweir                 Sequence< Type > interfaces = invokeGetTypes( *this, o );
858cdf0e10cSrcweir                 if( interfaces.getLength() )
859cdf0e10cSrcweir                 {
860cdf0e10cSrcweir                     Adapter *pAdapter = new Adapter( o, interfaces );
861cdf0e10cSrcweir                     mappedObject =
862cdf0e10cSrcweir                         getImpl()->cargo->xAdapterFactory->createAdapter(
863cdf0e10cSrcweir                             pAdapter, interfaces );
864cdf0e10cSrcweir 
865cdf0e10cSrcweir                     // keep a list of exported objects to ensure object identity !
866cdf0e10cSrcweir                     impl->cargo->mappedObjects[ PyRef(o) ] =
867cdf0e10cSrcweir                         com::sun::star::uno::WeakReference< XInvocation > ( pAdapter );
868cdf0e10cSrcweir                 }
869cdf0e10cSrcweir             }
870cdf0e10cSrcweir             if( mappedObject.is() )
871cdf0e10cSrcweir             {
872cdf0e10cSrcweir                 a = com::sun::star::uno::makeAny( mappedObject );
873cdf0e10cSrcweir             }
874cdf0e10cSrcweir             else
875cdf0e10cSrcweir             {
876cdf0e10cSrcweir                 OUStringBuffer buf;
877cdf0e10cSrcweir                 buf.appendAscii( "Couldn't convert " );
878cdf0e10cSrcweir                 PyRef reprString( PyObject_Str( o ) , SAL_NO_ACQUIRE );
879cdf0e10cSrcweir                 buf.appendAscii( PyString_AsString( reprString.get() ) );
880cdf0e10cSrcweir                 buf.appendAscii( " to a UNO type" );
881cdf0e10cSrcweir                 throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface > () );
882cdf0e10cSrcweir             }
883cdf0e10cSrcweir         }
884cdf0e10cSrcweir     }
885cdf0e10cSrcweir     return a;
886cdf0e10cSrcweir }
887cdf0e10cSrcweir 
888cdf0e10cSrcweir Any Runtime::extractUnoException( const PyRef & excType, const PyRef &excValue, const PyRef &excTraceback) const
889cdf0e10cSrcweir {
890cdf0e10cSrcweir     PyRef str;
891cdf0e10cSrcweir     Any ret;
892cdf0e10cSrcweir     if( excTraceback.is() )
893cdf0e10cSrcweir     {
894cdf0e10cSrcweir         PyRef unoModule( impl ? impl->cargo->getUnoModule() : 0 );
895cdf0e10cSrcweir         if( unoModule.is() )
896cdf0e10cSrcweir         {
897cdf0e10cSrcweir             PyRef extractTraceback(
898cdf0e10cSrcweir                 PyDict_GetItemString(unoModule.get(),"_uno_extract_printable_stacktrace" ) );
899cdf0e10cSrcweir 
900cdf0e10cSrcweir             if( extractTraceback.is() )
901cdf0e10cSrcweir             {
902cdf0e10cSrcweir                 PyRef args( PyTuple_New( 1), SAL_NO_ACQUIRE );
903cdf0e10cSrcweir                 PyTuple_SetItem( args.get(), 0, excTraceback.getAcquired() );
904cdf0e10cSrcweir                 str = PyRef( PyObject_CallObject( extractTraceback.get(),args.get() ), SAL_NO_ACQUIRE);
905cdf0e10cSrcweir             }
906cdf0e10cSrcweir             else
907cdf0e10cSrcweir             {
908cdf0e10cSrcweir                 str = PyRef(
909cdf0e10cSrcweir                     PyString_FromString( "Couldn't find uno._uno_extract_printable_stacktrace" ),
910cdf0e10cSrcweir                     SAL_NO_ACQUIRE );
911cdf0e10cSrcweir             }
912cdf0e10cSrcweir         }
913cdf0e10cSrcweir         else
914cdf0e10cSrcweir         {
915cdf0e10cSrcweir             str = PyRef(
916cdf0e10cSrcweir                 PyString_FromString( "Couldn't find uno.py, no stacktrace available" ),
917cdf0e10cSrcweir                 SAL_NO_ACQUIRE );
918cdf0e10cSrcweir         }
919cdf0e10cSrcweir 
920cdf0e10cSrcweir     }
921cdf0e10cSrcweir     else
922cdf0e10cSrcweir     {
923cdf0e10cSrcweir         // it may occur, that no traceback is given (e.g. only native code below)
924cdf0e10cSrcweir         str = PyRef( PyString_FromString( "no traceback available" ), SAL_NO_ACQUIRE);
925cdf0e10cSrcweir     }
926cdf0e10cSrcweir 
927cdf0e10cSrcweir     if( isInstanceOfStructOrException( excValue.get() ) )
928cdf0e10cSrcweir     {
929cdf0e10cSrcweir         ret = pyObject2Any( excValue );
930cdf0e10cSrcweir     }
931cdf0e10cSrcweir     else
932cdf0e10cSrcweir     {
933cdf0e10cSrcweir         OUStringBuffer buf;
934cdf0e10cSrcweir         PyRef typeName( PyObject_Str( excType.get() ), SAL_NO_ACQUIRE );
935cdf0e10cSrcweir         if( typeName.is() )
936cdf0e10cSrcweir         {
937cdf0e10cSrcweir             buf.appendAscii( PyString_AsString( typeName.get() ) );
938cdf0e10cSrcweir         }
939cdf0e10cSrcweir         else
940cdf0e10cSrcweir         {
941cdf0e10cSrcweir             buf.appendAscii( "no typename available" );
942cdf0e10cSrcweir         }
943cdf0e10cSrcweir         buf.appendAscii( ": " );
944cdf0e10cSrcweir         PyRef valueRep( PyObject_Str( excValue.get() ), SAL_NO_ACQUIRE );
945cdf0e10cSrcweir         if( valueRep.is() )
946cdf0e10cSrcweir         {
947cdf0e10cSrcweir             buf.appendAscii( PyString_AsString( valueRep.get()));
948cdf0e10cSrcweir         }
949cdf0e10cSrcweir         else
950cdf0e10cSrcweir         {
951cdf0e10cSrcweir             buf.appendAscii( "Couldn't convert exception value to a string" );
952cdf0e10cSrcweir         }
953cdf0e10cSrcweir         buf.appendAscii( ", traceback follows\n" );
954cdf0e10cSrcweir         if( str.is() )
955cdf0e10cSrcweir         {
956cdf0e10cSrcweir             buf.appendAscii( PyString_AsString( str.get() ) );
957cdf0e10cSrcweir         }
958cdf0e10cSrcweir         else
959cdf0e10cSrcweir         {
960cdf0e10cSrcweir             buf.appendAscii( ", no traceback available\n" );
961cdf0e10cSrcweir         }
962cdf0e10cSrcweir         RuntimeException e;
963cdf0e10cSrcweir         e.Message = buf.makeStringAndClear();
964cdf0e10cSrcweir         ret = com::sun::star::uno::makeAny( e );
965cdf0e10cSrcweir     }
966cdf0e10cSrcweir     return ret;
967cdf0e10cSrcweir }
968cdf0e10cSrcweir 
969cdf0e10cSrcweir 
970cdf0e10cSrcweir static const char * g_NUMERICID = "pyuno.lcNumeric";
971cdf0e10cSrcweir static ::std::vector< rtl::OString > g_localeList;
972cdf0e10cSrcweir 
973cdf0e10cSrcweir static const char *ensureUnlimitedLifetime( const char *str )
974cdf0e10cSrcweir {
975cdf0e10cSrcweir     int size = g_localeList.size();
976cdf0e10cSrcweir     int i;
977cdf0e10cSrcweir     for( i = 0 ; i < size ; i ++ )
978cdf0e10cSrcweir     {
979cdf0e10cSrcweir         if( 0 == strcmp( g_localeList[i].getStr(), str ) )
980cdf0e10cSrcweir             break;
981cdf0e10cSrcweir     }
982cdf0e10cSrcweir     if( i == size )
983cdf0e10cSrcweir     {
984cdf0e10cSrcweir         g_localeList.push_back( str );
985cdf0e10cSrcweir     }
986cdf0e10cSrcweir     return g_localeList[i].getStr();
987cdf0e10cSrcweir }
988cdf0e10cSrcweir 
989cdf0e10cSrcweir 
990cdf0e10cSrcweir PyThreadAttach::PyThreadAttach( PyInterpreterState *interp)
991cdf0e10cSrcweir     throw ( com::sun::star::uno::RuntimeException )
992cdf0e10cSrcweir {
993cdf0e10cSrcweir     tstate = PyThreadState_New( interp );
994cdf0e10cSrcweir     if( !tstate  )
995cdf0e10cSrcweir         throw RuntimeException(
996cdf0e10cSrcweir             OUString(RTL_CONSTASCII_USTRINGPARAM( "Couldn't create a pythreadstate" ) ),
997cdf0e10cSrcweir             Reference< XInterface > () );
998cdf0e10cSrcweir     PyEval_AcquireThread( tstate);
999cdf0e10cSrcweir     // set LC_NUMERIC to "C"
1000cdf0e10cSrcweir     const char * oldLocale =
1001cdf0e10cSrcweir         ensureUnlimitedLifetime( setlocale( LC_NUMERIC, 0 )  );
1002cdf0e10cSrcweir     setlocale( LC_NUMERIC, "C" );
1003cdf0e10cSrcweir     PyRef locale( // python requires C locale
1004cdf0e10cSrcweir         PyLong_FromVoidPtr( (void*)oldLocale ), SAL_NO_ACQUIRE);
1005cdf0e10cSrcweir     PyDict_SetItemString(
1006cdf0e10cSrcweir         PyThreadState_GetDict(), g_NUMERICID, locale.get() );
1007cdf0e10cSrcweir }
1008cdf0e10cSrcweir 
1009cdf0e10cSrcweir PyThreadAttach::~PyThreadAttach()
1010cdf0e10cSrcweir {
1011cdf0e10cSrcweir     PyObject *value =
1012cdf0e10cSrcweir         PyDict_GetItemString( PyThreadState_GetDict( ), g_NUMERICID );
1013cdf0e10cSrcweir     if( value )
1014cdf0e10cSrcweir         setlocale( LC_NUMERIC, (const char * ) PyLong_AsVoidPtr( value ) );
1015cdf0e10cSrcweir     PyThreadState_Clear( tstate );
1016cdf0e10cSrcweir     PyEval_ReleaseThread( tstate );
1017cdf0e10cSrcweir     PyThreadState_Delete( tstate );
1018cdf0e10cSrcweir 
1019cdf0e10cSrcweir }
1020cdf0e10cSrcweir 
1021cdf0e10cSrcweir PyThreadDetach::PyThreadDetach() throw ( com::sun::star::uno::RuntimeException )
1022cdf0e10cSrcweir {
1023cdf0e10cSrcweir     tstate = PyThreadState_Get();
1024cdf0e10cSrcweir     PyObject *value =
1025cdf0e10cSrcweir         PyDict_GetItemString( PyThreadState_GetDict( ), g_NUMERICID );
1026cdf0e10cSrcweir     if( value )
1027cdf0e10cSrcweir         setlocale( LC_NUMERIC, (const char * ) PyLong_AsVoidPtr( value ) );
1028cdf0e10cSrcweir     PyEval_ReleaseThread( tstate );
1029cdf0e10cSrcweir }
1030cdf0e10cSrcweir 
1031cdf0e10cSrcweir     /** Acquires the global interpreter lock again
1032cdf0e10cSrcweir 
1033cdf0e10cSrcweir     */
1034cdf0e10cSrcweir PyThreadDetach::~PyThreadDetach()
1035cdf0e10cSrcweir {
1036cdf0e10cSrcweir     PyEval_AcquireThread( tstate );
1037cdf0e10cSrcweir //     PyObject *value =
1038cdf0e10cSrcweir //         PyDict_GetItemString( PyThreadState_GetDict( ), g_NUMERICID );
1039cdf0e10cSrcweir 
1040cdf0e10cSrcweir     // python requires C LC_NUMERIC locale,
1041cdf0e10cSrcweir     // always set even when it is already "C"
1042cdf0e10cSrcweir     setlocale( LC_NUMERIC, "C" );
1043cdf0e10cSrcweir }
1044cdf0e10cSrcweir 
1045cdf0e10cSrcweir 
1046cdf0e10cSrcweir PyRef RuntimeCargo::getUnoModule()
1047cdf0e10cSrcweir {
1048cdf0e10cSrcweir     if( ! dictUnoModule.is() )
1049cdf0e10cSrcweir     {
1050cdf0e10cSrcweir         dictUnoModule = importUnoModule();
1051cdf0e10cSrcweir     }
1052cdf0e10cSrcweir     return dictUnoModule;
1053cdf0e10cSrcweir }
1054cdf0e10cSrcweir }
1055