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