xref: /trunk/main/bridges/source/cpp_uno/msvc_win64_x86-64/uno2cpp.cxx (revision af7f2cbf3d6a5481a2f45e7fae5e85a32449c47d)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_bridges.hxx"
26 
27 #include <malloc.h>
28 
29 #include <com/sun/star/uno/genfunc.hxx>
30 #include <uno/data.h>
31 
32 #include "bridges/cpp_uno/shared/bridge.hxx"
33 #include "bridges/cpp_uno/shared/types.hxx"
34 #include "bridges/cpp_uno/shared/unointerfaceproxy.hxx"
35 #include "bridges/cpp_uno/shared/vtables.hxx"
36 
37 #include "abi.hxx"
38 #include "mscx.hxx"
39 
40 using namespace ::rtl;
41 using namespace ::com::sun::star::uno;
42 
43 namespace
44 {
45 
46 //==================================================================================================
47 extern "C" void callVirtualMethod(
48     void * pAdjustedThisPtr, sal_Int32 nVtableIndex,
49     void * pRegisterReturn, typelib_TypeClass eReturnTypeClass,
50     sal_uInt64 * pStackLongs, sal_uInt32 nStackLongs );
51 
52 //==================================================================================================
53 static void cpp_call(
54     bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,
55     bridges::cpp_uno::shared::VtableSlot aVtableSlot,
56     typelib_TypeDescriptionReference * pReturnTypeRef,
57     sal_Int32 nParams, typelib_MethodParameter * pParams,
58     void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) throw ()
59 {
60     // max space for: [complex ret ptr], values|ptr ...
61     sal_uInt64 *pStack = (sal_uInt64 *)alloca( (nParams + 3) * sizeof(sal_uInt64) );
62     sal_uInt64 *pStackStart = pStack;
63 
64     // Push "this" pointer
65     void * pAdjustedThisPtr = reinterpret_cast< void ** >( pThis->getCppI() ) + aVtableSlot.offset;
66     *pStack++ = *(sal_uInt64*)&pAdjustedThisPtr;
67 
68     // return
69     typelib_TypeDescription * pReturnTypeDescr = 0;
70     TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
71     OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" );
72 
73     void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion
74 
75     if ( pReturnTypeDescr )
76     {
77         if ( x86_64::return_in_hidden_param( pReturnTypeRef ) )
78         {
79             // complex return via ptr
80             pCppReturn = bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )?
81                          alloca( pReturnTypeDescr->nSize ) : pUnoReturn; // direct way
82             *pStack++ = *(sal_uInt64*)&pCppReturn;
83         }
84         else
85             pCppReturn = pUnoReturn; // direct way for simple types
86     }
87 
88     // Args
89     void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams );
90     // Indices of values this have to be converted (interface conversion cpp<=>uno)
91     sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams);
92     // Type descriptions for reconversions
93     typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
94 
95     sal_Int32 nTempIndizes = 0;
96 
97     for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
98     {
99         const typelib_MethodParameter & rParam = pParams[nPos];
100         typelib_TypeDescription * pParamTypeDescr = 0;
101         TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
102 
103         if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
104         {
105             uno_copyAndConvertData( pCppArgs[nPos] = alloca( 8 ), pUnoArgs[nPos], pParamTypeDescr,
106                                     pThis->getBridge()->getUno2Cpp() );
107 
108             switch (pParamTypeDescr->eTypeClass)
109             {
110             case typelib_TypeClass_HYPER:
111             case typelib_TypeClass_UNSIGNED_HYPER:
112                 *pStack++ = *(sal_uInt64*)&pCppArgs[nPos];
113                 break;
114             case typelib_TypeClass_LONG:
115             case typelib_TypeClass_UNSIGNED_LONG:
116             case typelib_TypeClass_ENUM:
117                 *pStack++ = *(sal_uInt32*)&pCppArgs[nPos];
118                 break;
119             case typelib_TypeClass_SHORT:
120             case typelib_TypeClass_UNSIGNED_SHORT:
121             case typelib_TypeClass_CHAR:
122                 *pStack++ = *(sal_uInt16*)&pCppArgs[nPos];
123                 break;
124             case typelib_TypeClass_BOOLEAN:
125             case typelib_TypeClass_BYTE:
126                 *pStack++ = *(sal_uInt8*)&pCppArgs[nPos];
127                 break;
128             case typelib_TypeClass_FLOAT:
129             case typelib_TypeClass_DOUBLE:
130                 *pStack++ = *(sal_uInt64*)&pCppArgs[nPos]; // verbatim!
131                 break;
132             default:
133                 break;
134             }
135             // no longer needed
136             TYPELIB_DANGER_RELEASE( pParamTypeDescr );
137         }
138         else // ptr to complex value | ref
139         {
140             if (! rParam.bIn) // is pure out
141             {
142                 // cpp out is constructed mem, uno out is not!
143                 uno_constructData(
144                     pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
145                     pParamTypeDescr );
146                 pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call
147                 // will be released at reconversion
148                 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
149             }
150             // is in/inout
151             else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
152             {
153                 uno_copyAndConvertData(
154                     pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
155                     pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
156 
157                 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
158                 // will be released at reconversion
159                 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
160             }
161             else // direct way
162             {
163                 pCppArgs[nPos] = pUnoArgs[nPos];
164                 // no longer needed
165                 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
166             }
167             *pStack++ = *(sal_uInt64*)&pCppArgs[nPos];
168         }
169     }
170 
171     __try
172     {
173         // pCppI is mscx this pointer
174         callVirtualMethod(
175             pAdjustedThisPtr,
176             aVtableSlot.index,
177             pCppReturn, pReturnTypeDescr->eTypeClass,
178             pStackStart, (pStack - pStackStart) );
179     }
180     __except (CPPU_CURRENT_NAMESPACE::mscx_filterCppException(
181                   GetExceptionInformation(),
182                   *ppUnoExc, pThis->getBridge()->getCpp2Uno() ))
183    {
184         // *ppUnoExc was constructed by filter function
185         // temporary params
186         for ( ; nTempIndizes--; )
187         {
188             sal_Int32 nIndex = pTempIndizes[nTempIndizes];
189             // destroy temp cpp param => cpp: every param was constructed
190             uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release );
191             TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
192         }
193         // return type
194         if (pReturnTypeDescr)
195             TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
196         // end here
197         return;
198     }
199 
200     // NO exception occurred
201     *ppUnoExc = 0;
202 
203     // reconvert temporary params
204     for ( ; nTempIndizes--; )
205     {
206         sal_Int32 nIndex = pTempIndizes[nTempIndizes];
207         typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
208 
209         if (pParams[nIndex].bIn)
210         {
211             if (pParams[nIndex].bOut) // inout
212             {
213                 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value
214                 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
215                                         pThis->getBridge()->getCpp2Uno() );
216             }
217         }
218         else // pure out
219         {
220             uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
221                                     pThis->getBridge()->getCpp2Uno() );
222         }
223         // destroy temp cpp param => cpp: every param was constructed
224         uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
225 
226         TYPELIB_DANGER_RELEASE( pParamTypeDescr );
227     }
228     // return value
229     if (pCppReturn && pUnoReturn != pCppReturn)
230     {
231         uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr,
232                                 pThis->getBridge()->getCpp2Uno() );
233         uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release );
234     }
235     // return type
236     if (pReturnTypeDescr)
237         TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
238 }
239 
240 }
241 
242 namespace bridges { namespace cpp_uno { namespace shared {
243 
244 void unoInterfaceProxyDispatch(
245     uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
246     void * pReturn, void * pArgs[], uno_Any ** ppException )
247 {
248     // is my surrogate
249     bridges::cpp_uno::shared::UnoInterfaceProxy * pThis
250         = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI);
251 
252     switch (pMemberDescr->eTypeClass)
253     {
254     case typelib_TypeClass_INTERFACE_ATTRIBUTE:
255     {
256         VtableSlot aVtableSlot(
257             getVtableSlot(
258                 reinterpret_cast<
259                     typelib_InterfaceAttributeTypeDescription const * >(
260                         pMemberDescr)));
261 
262         if (pReturn)
263         {
264             // dependent dispatch
265             cpp_call(
266                 pThis, aVtableSlot,
267                 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
268                 0, 0, // no params
269                 pReturn, pArgs, ppException );
270         }
271         else
272         {
273             // is SET
274             typelib_MethodParameter aParam;
275             aParam.pTypeRef =
276                 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
277             aParam.bIn      = sal_True;
278             aParam.bOut     = sal_False;
279 
280             typelib_TypeDescriptionReference * pReturnTypeRef = 0;
281             OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") );
282             typelib_typedescriptionreference_new(
283                 &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
284 
285             // dependent dispatch
286             aVtableSlot.index += 1; // get, then set method
287             cpp_call(
288                 pThis, aVtableSlot, // get, then set method
289                 pReturnTypeRef,
290                 1, &aParam,
291                 pReturn, pArgs, ppException );
292 
293             typelib_typedescriptionreference_release( pReturnTypeRef );
294         }
295 
296         break;
297     }
298     case typelib_TypeClass_INTERFACE_METHOD:
299     {
300         VtableSlot aVtableSlot(
301             getVtableSlot(
302                 reinterpret_cast<
303                     typelib_InterfaceMethodTypeDescription const * >(
304                         pMemberDescr)));
305 
306         switch (aVtableSlot.index)
307         {
308             // standard calls
309         case 1: // acquire uno interface
310             (*pUnoI->acquire)( pUnoI );
311             *ppException = 0;
312             break;
313         case 2: // release uno interface
314             (*pUnoI->release)( pUnoI );
315             *ppException = 0;
316             break;
317         case 0: // queryInterface() opt
318         {
319             typelib_TypeDescription * pTD = 0;
320             TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
321             if (pTD)
322             {
323                 uno_Interface * pInterface = 0;
324                 (*pThis->getBridge()->getUnoEnv()->getRegisteredInterface)(
325                     pThis->getBridge()->getUnoEnv(),
326                     (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
327 
328                 if (pInterface)
329                 {
330                     ::uno_any_construct(
331                         reinterpret_cast< uno_Any * >( pReturn ),
332                         &pInterface, pTD, 0 );
333                     (*pInterface->release)( pInterface );
334                     TYPELIB_DANGER_RELEASE( pTD );
335                     *ppException = 0;
336                     break;
337                 }
338                 TYPELIB_DANGER_RELEASE( pTD );
339             }
340         } // else perform queryInterface()
341         default:
342             // dependent dispatch
343             cpp_call(
344                 pThis, aVtableSlot,
345                 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
346                 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
347                 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
348                 pReturn, pArgs, ppException );
349         }
350         break;
351     }
352     default:
353     {
354         ::com::sun::star::uno::RuntimeException aExc(
355             OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ),
356             ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
357 
358         Type const & rExcType = ::getCppuType( &aExc );
359         // binary identical null reference
360         ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
361     }
362     }
363 }
364 
365 } } }
366