xref: /trunk/main/bridges/source/cpp_uno/cc50_solaris_sparc/uno2cpp.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_bridges.hxx"
30 
31 #include <sal/alloca.h>
32 
33 #include <com/sun/star/uno/genfunc.hxx>
34 #include "com/sun/star/uno/RuntimeException.hpp"
35 #include <uno/data.h>
36 
37 #include "bridges/cpp_uno/shared/bridge.hxx"
38 #include "bridges/cpp_uno/shared/types.hxx"
39 #include "bridges/cpp_uno/shared/unointerfaceproxy.hxx"
40 #include "bridges/cpp_uno/shared/vtables.hxx"
41 
42 #include "cc50_solaris_sparc.hxx"
43 
44 using namespace rtl;
45 using namespace com::sun::star::uno;
46 
47 namespace
48 {
49 
50 extern "C" void callVirtualMethod(
51         void * pAdjustedThisPtr,
52         sal_Int32 nVtableIndex,
53         void * pRegisterReturn,
54         typelib_TypeClass eReturnType,
55         sal_Int32 * pStackLongs,
56         sal_Int32 nStackLongs
57     );
58 
59 //==================================================================================================
60 static void cpp_call(
61     bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,
62     bridges::cpp_uno::shared::VtableSlot aVtableSlot,
63     typelib_TypeDescriptionReference * pReturnTypeRef,
64     sal_Int32 nParams, typelib_MethodParameter * pParams,
65     void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc )
66 {
67     // pCppI is cc50_solaris_sparc this pointer
68     OSL_ENSURE( pThis, "### no interface given!" );
69 
70     // max space for: [complex ret ptr], values|ptr ...
71     char * pCppStack        = (char *)alloca( ((nParams+3) * sizeof(sal_Int64)) );
72     char * pCppStackStart   = pCppStack;
73 
74     // return
75     typelib_TypeDescription * pReturnTypeDescr = 0;
76     TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
77     OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" );
78 
79     void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion
80 
81     if (pReturnTypeDescr)
82     {
83         if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
84         {
85             pCppReturn = pUnoReturn; // direct way for simple types
86         }
87         else
88         {
89             // complex return via ptr
90             pCppReturn = *(void **)pCppStack
91                 = (bridges::cpp_uno::shared::relatesToInterfaceType(
92                        pReturnTypeDescr )
93                    ? alloca( pReturnTypeDescr->nSize )
94                    : pUnoReturn); // direct way
95             pCppStack += sizeof(void *);
96         }
97     }
98     // push this
99     void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI())
100         + aVtableSlot.offset;
101     *(void**)pCppStack = pAdjustedThisPtr;
102     pCppStack += sizeof( void* );
103 
104     // args
105     void ** pCppArgs  = (void **)alloca( 3 * sizeof(void *) * nParams );
106     // indizes of values this have to be converted (interface conversion cpp<=>uno)
107     sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams);
108     // type descriptions for reconversions
109     typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
110 
111     sal_Int32 nTempIndizes   = 0;
112 
113     for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
114     {
115         const typelib_MethodParameter & rParam = pParams[nPos];
116         typelib_TypeDescription * pParamTypeDescr = 0;
117         TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
118 
119         if (!rParam.bOut
120             && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
121         {
122             pCppArgs[ nPos ] = CPPU_CURRENT_NAMESPACE::adjustPointer(
123                 pCppStack, pParamTypeDescr );
124             uno_copyAndConvertData( pCppArgs[nPos], pUnoArgs[nPos], pParamTypeDescr,
125                                     pThis->getBridge()->getUno2Cpp() );
126 
127             switch (pParamTypeDescr->eTypeClass)
128             {
129             case typelib_TypeClass_HYPER:
130             case typelib_TypeClass_UNSIGNED_HYPER:
131             case typelib_TypeClass_DOUBLE:
132                 pCppStack += sizeof(sal_Int32); // extra long
133             }
134             // no longer needed
135             TYPELIB_DANGER_RELEASE( pParamTypeDescr );
136         }
137         else // ptr to complex value | ref
138         {
139             if (! rParam.bIn) // is pure out
140             {
141                 // cpp out is constructed mem, uno out is not!
142                 uno_constructData(
143                     *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
144                     pParamTypeDescr );
145                 pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call
146                 // will be released at reconversion
147                 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
148             }
149             // is in/inout
150             else if (bridges::cpp_uno::shared::relatesToInterfaceType(
151                          pParamTypeDescr ))
152             {
153                 uno_copyAndConvertData(
154                     *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
155                     pUnoArgs[nPos], pParamTypeDescr,
156                     pThis->getBridge()->getUno2Cpp() );
157 
158                 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
159                 // will be released at reconversion
160                 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
161             }
162             else // direct way
163             {
164                 *(void **)pCppStack = pCppArgs[nPos] = pUnoArgs[nPos];
165                 // no longer needed
166                 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
167             }
168         }
169         pCppStack += sizeof(sal_Int32); // standard parameter length
170     }
171 
172 // seems that EH registration for callVirtualMethod is not really
173 // necessary
174 
175 //  static unsigned long* pFrameInfo = NULL;
176 
177 //  if( ! pFrameInfo )
178 //  {
179 //      pFrameInfo = new unsigned long[ 7 ];
180 //      pFrameInfo[ 0 ] = 0x40000000 | (((unsigned long)__Crun::ex_rethrow_q) >> 2);
181 //      pFrameInfo[ 1 ] = 0x01000000;
182 //      pFrameInfo[ 2 ] = (unsigned long)callVirtualMethodExceptionHandler;
183 //      pFrameInfo[ 3 ] = 0;
184 //          pFrameInfo[ 4 ] = (unsigned long)pFrameInfo - (unsigned long)callVirtualMethodExceptionHandler;
185 //      pFrameInfo[ 5 ] = 0;
186 //      pFrameInfo[ 6 ] = 0;
187 //      _ex_register( pFrameInfo+2, 1 );
188 //  }
189 
190     try
191     {
192         int nStackLongs = (pCppStack - pCppStackStart)/sizeof(sal_Int32);
193         if( nStackLongs & 1 )
194             // stack has to be 8 byte aligned
195             nStackLongs++;
196 
197         callVirtualMethod(
198             pAdjustedThisPtr,
199             aVtableSlot.index,
200             pCppReturn,
201             pReturnTypeDescr->eTypeClass,
202             (sal_Int32 *)pCppStackStart,
203             nStackLongs
204             );
205 
206         // NO exception occured...
207         *ppUnoExc = 0;
208 
209         // reconvert temporary params
210         for ( ; nTempIndizes--; )
211         {
212             sal_Int32 nIndex = pTempIndizes[nTempIndizes];
213             typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
214 
215             if (pParams[nIndex].bIn)
216             {
217                 if (pParams[nIndex].bOut) // inout
218                 {
219                     uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value
220                     uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
221                                             pThis->getBridge()->getCpp2Uno() );
222                 }
223             }
224             else // pure out
225             {
226                 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
227                                         pThis->getBridge()->getCpp2Uno() );
228             }
229             // destroy temp cpp param => cpp: every param was constructed
230             uno_destructData(
231                 pCppArgs[nIndex], pParamTypeDescr,
232                 reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
233 
234             TYPELIB_DANGER_RELEASE( pParamTypeDescr );
235         }
236         // return value
237         if (pCppReturn && pUnoReturn != pCppReturn)
238         {
239             uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr,
240                                     pThis->getBridge()->getCpp2Uno() );
241             uno_destructData(
242                 pCppReturn, pReturnTypeDescr,
243                 reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
244         }
245     }
246     catch( ... )
247     {
248         void* pExc = __Crun::ex_get();
249         const char* pName = __Cimpl::ex_name();
250 
251         // get exception
252         CPPU_CURRENT_NAMESPACE::cc50_solaris_sparc_fillUnoException(
253             pExc, pName, *ppUnoExc, pThis->getBridge()->getCpp2Uno());
254 
255         // temporary params
256         for ( ; nTempIndizes--; )
257         {
258             sal_Int32 nIndex = pTempIndizes[nTempIndizes];
259             // destroy temp cpp param => cpp: every param was constructed
260             uno_destructData(
261                 pCppArgs[nIndex],
262                 ppTempParamTypeDescr[nTempIndizes],
263                 reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
264             TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
265         }
266         // return type
267         if (pReturnTypeDescr)
268             TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
269     }
270 }
271 
272 }
273 
274 namespace bridges { namespace cpp_uno { namespace shared {
275 
276 void unoInterfaceProxyDispatch(
277     uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
278     void * pReturn, void * pArgs[], uno_Any ** ppException )
279 {
280     // is my surrogate
281     bridges::cpp_uno::shared::UnoInterfaceProxy * pThis
282         = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI);
283     typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr;
284 
285     switch (pMemberDescr->eTypeClass)
286     {
287     case typelib_TypeClass_INTERFACE_ATTRIBUTE:
288     {
289         VtableSlot aVtableSlot(
290             getVtableSlot(
291                 reinterpret_cast<
292                     typelib_InterfaceAttributeTypeDescription const * >(
293                         pMemberDescr)));
294         if (pReturn)
295         {
296             // dependent dispatch
297             cpp_call(
298                 pThis, aVtableSlot,
299                 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
300                 0, 0, // no params
301                 pReturn, pArgs, ppException );
302         }
303         else
304         {
305             // is SET
306             typelib_MethodParameter aParam;
307             aParam.pTypeRef =
308                 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
309             aParam.bIn      = sal_True;
310             aParam.bOut     = sal_False;
311 
312             typelib_TypeDescriptionReference * pReturnTypeRef = 0;
313             OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") );
314             typelib_typedescriptionreference_new(
315                 &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
316 
317             // dependent dispatch
318             aVtableSlot.index += 1; // get, then set method
319             cpp_call(
320                 pThis, aVtableSlot,
321                 pReturnTypeRef,
322                 1, &aParam,
323                 pReturn, pArgs, ppException );
324 
325             typelib_typedescriptionreference_release( pReturnTypeRef );
326         }
327 
328         break;
329     }
330     case typelib_TypeClass_INTERFACE_METHOD:
331     {
332         VtableSlot aVtableSlot(
333             getVtableSlot(
334                 reinterpret_cast<
335                     typelib_InterfaceMethodTypeDescription const * >(
336                         pMemberDescr)));
337         switch (aVtableSlot.index)
338         {
339             // standard calls
340         case 1: // acquire uno interface
341             (*pUnoI->acquire)( pUnoI );
342             *ppException = 0;
343             break;
344         case 2: // release uno interface
345             (*pUnoI->release)( pUnoI );
346             *ppException = 0;
347             break;
348         case 0: // queryInterface() opt
349         {
350             typelib_TypeDescription * pTD = 0;
351             TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
352             if (pTD)
353             {
354                 uno_Interface * pInterface = 0;
355                 (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)(
356                     pThis->pBridge->getUnoEnv(),
357                     (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
358 
359                 if (pInterface)
360                 {
361                     ::uno_any_construct(
362                         reinterpret_cast< uno_Any * >( pReturn ),
363                         &pInterface, pTD, 0 );
364                     (*pInterface->release)( pInterface );
365                     TYPELIB_DANGER_RELEASE( pTD );
366                     *ppException = 0;
367                     break;
368                 }
369                 TYPELIB_DANGER_RELEASE( pTD );
370             }
371         } // else perform queryInterface()
372         default:
373             // dependent dispatch
374             cpp_call(
375                 pThis, aVtableSlot,
376                 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
377                 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
378                 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
379                 pReturn, pArgs, ppException );
380         }
381         break;
382     }
383     default:
384     {
385         ::com::sun::star::uno::RuntimeException aExc(
386             OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ),
387             ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
388 
389         Type const & rExcType = ::getCppuType( &aExc );
390         // binary identical null reference
391         ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
392     }
393     }
394 }
395 
396 } } }
397