Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #if defined (FREEBSD) || defined(NETBSD) || defined(OPENBSD) || defined(DRAGONFLY)
22 : #include <stdlib.h>
23 : #else
24 : #include <alloca.h>
25 : #endif
26 :
27 : #include <com/sun/star/uno/genfunc.hxx>
28 : #include "com/sun/star/uno/RuntimeException.hpp"
29 : #include <uno/data.h>
30 :
31 : #include "bridges/cpp_uno/shared/bridge.hxx"
32 : #include "bridges/cpp_uno/shared/types.hxx"
33 : #include "bridges/cpp_uno/shared/unointerfaceproxy.hxx"
34 : #include "bridges/cpp_uno/shared/vtables.hxx"
35 :
36 : #include "callvirtualmethod.hxx"
37 : #include "share.hxx"
38 :
39 : using namespace ::rtl;
40 : using namespace ::com::sun::star::uno;
41 :
42 : namespace
43 : {
44 :
45 0 : static void cpp_call(
46 : bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,
47 : bridges::cpp_uno::shared::VtableSlot aVtableSlot,
48 : typelib_TypeDescriptionReference * pReturnTypeRef,
49 : sal_Int32 nParams, typelib_MethodParameter * pParams,
50 : void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc )
51 : {
52 : // max space for: [complex ret ptr], values|ptr ...
53 : char * pCppStack =
54 0 : (char *)alloca( sizeof(sal_Int32) + ((nParams+2) * sizeof(sal_Int64)) );
55 0 : char * pCppStackStart = pCppStack;
56 :
57 : // return
58 0 : typelib_TypeDescription * pReturnTypeDescr = 0;
59 0 : TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
60 : OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" );
61 :
62 0 : void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion
63 0 : bool bSimpleReturn = true;
64 :
65 0 : if (pReturnTypeDescr)
66 : {
67 0 : bSimpleReturn = x86::isSimpleReturnType(pReturnTypeDescr);
68 0 : if (bSimpleReturn)
69 : {
70 0 : pCppReturn = pUnoReturn; // direct way for simple types
71 : }
72 : else
73 : {
74 : // complex return via ptr
75 : pCppReturn = *(void **)pCppStack
76 : = (bridges::cpp_uno::shared::relatesToInterfaceType(
77 0 : pReturnTypeDescr )
78 0 : ? alloca( pReturnTypeDescr->nSize )
79 0 : : pUnoReturn); // direct way
80 0 : pCppStack += sizeof(void *);
81 : }
82 : }
83 : // push this
84 0 : void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI())
85 0 : + aVtableSlot.offset;
86 0 : *(void**)pCppStack = pAdjustedThisPtr;
87 0 : pCppStack += sizeof( void* );
88 :
89 : // stack space
90 : OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" );
91 : // args
92 0 : void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams );
93 : // indices of values this have to be converted (interface conversion cpp<=>uno)
94 0 : sal_Int32 * pTempIndices = (sal_Int32 *)(pCppArgs + nParams);
95 : // type descriptions for reconversions
96 0 : typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
97 :
98 0 : sal_Int32 nTempIndices = 0;
99 :
100 0 : for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
101 : {
102 0 : const typelib_MethodParameter & rParam = pParams[nPos];
103 0 : typelib_TypeDescription * pParamTypeDescr = 0;
104 0 : TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
105 :
106 0 : if (!rParam.bOut
107 0 : && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
108 : {
109 0 : uno_copyAndConvertData( pCppArgs[nPos] = pCppStack, pUnoArgs[nPos], pParamTypeDescr,
110 0 : pThis->getBridge()->getUno2Cpp() );
111 :
112 0 : switch (pParamTypeDescr->eTypeClass)
113 : {
114 : case typelib_TypeClass_HYPER:
115 : case typelib_TypeClass_UNSIGNED_HYPER:
116 : case typelib_TypeClass_DOUBLE:
117 0 : pCppStack += sizeof(sal_Int32); // extra long
118 0 : break;
119 : default:
120 0 : break;
121 : }
122 : // no longer needed
123 0 : TYPELIB_DANGER_RELEASE( pParamTypeDescr );
124 : }
125 : else // ptr to complex value | ref
126 : {
127 0 : if (! rParam.bIn) // is pure out
128 : {
129 : // cpp out is constructed mem, uno out is not!
130 : uno_constructData(
131 0 : *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
132 0 : pParamTypeDescr );
133 0 : pTempIndices[nTempIndices] = nPos; // default constructed for cpp call
134 : // will be released at reconversion
135 0 : ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
136 : }
137 : // is in/inout
138 0 : else if (bridges::cpp_uno::shared::relatesToInterfaceType(
139 0 : pParamTypeDescr ))
140 : {
141 : uno_copyAndConvertData(
142 0 : *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
143 0 : pUnoArgs[nPos], pParamTypeDescr,
144 0 : pThis->getBridge()->getUno2Cpp() );
145 :
146 0 : pTempIndices[nTempIndices] = nPos; // has to be reconverted
147 : // will be released at reconversion
148 0 : ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
149 : }
150 : else // direct way
151 : {
152 0 : *(void **)pCppStack = pCppArgs[nPos] = pUnoArgs[nPos];
153 : // no longer needed
154 0 : TYPELIB_DANGER_RELEASE( pParamTypeDescr );
155 : }
156 : }
157 0 : pCppStack += sizeof(sal_Int32); // standard parameter length
158 : }
159 :
160 : try
161 : {
162 : OSL_ENSURE( !( (pCppStack - pCppStackStart ) & 3), "UNALIGNED STACK !!! (Please DO panic)" );
163 : CPPU_CURRENT_NAMESPACE::callVirtualMethod(
164 : pAdjustedThisPtr, aVtableSlot.index,
165 : pCppReturn, pReturnTypeDescr, bSimpleReturn,
166 0 : (sal_Int32 *)pCppStackStart, (pCppStack - pCppStackStart) / sizeof(sal_Int32) );
167 : // NO exception occurred...
168 0 : *ppUnoExc = 0;
169 :
170 : // reconvert temporary params
171 0 : for ( ; nTempIndices--; )
172 : {
173 0 : sal_Int32 nIndex = pTempIndices[nTempIndices];
174 0 : typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndices];
175 :
176 0 : if (pParams[nIndex].bIn)
177 : {
178 0 : if (pParams[nIndex].bOut) // inout
179 : {
180 0 : uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value
181 0 : uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
182 0 : pThis->getBridge()->getCpp2Uno() );
183 : }
184 : }
185 : else // pure out
186 : {
187 0 : uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
188 0 : pThis->getBridge()->getCpp2Uno() );
189 : }
190 : // destroy temp cpp param => cpp: every param was constructed
191 0 : uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
192 :
193 0 : TYPELIB_DANGER_RELEASE( pParamTypeDescr );
194 : }
195 : // return value
196 0 : if (pCppReturn && pUnoReturn != pCppReturn)
197 : {
198 : uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr,
199 0 : pThis->getBridge()->getCpp2Uno() );
200 0 : uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release );
201 : }
202 : }
203 0 : catch (...)
204 : {
205 : // fill uno exception
206 : fillUnoException(
207 : reinterpret_cast< CPPU_CURRENT_NAMESPACE::__cxa_eh_globals * >(
208 0 : __cxxabiv1::__cxa_get_globals())->caughtExceptions,
209 0 : *ppUnoExc, pThis->getBridge()->getCpp2Uno());
210 :
211 : // temporary params
212 0 : for ( ; nTempIndices--; )
213 : {
214 0 : sal_Int32 nIndex = pTempIndices[nTempIndices];
215 : // destroy temp cpp param => cpp: every param was constructed
216 0 : uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndices], cpp_release );
217 0 : TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndices] );
218 : }
219 : // return type
220 0 : if (pReturnTypeDescr)
221 0 : TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
222 : }
223 0 : }
224 :
225 : }
226 :
227 : namespace x86
228 : {
229 0 : bool isSimpleReturnType(typelib_TypeDescription * pTD, bool recursive)
230 : {
231 0 : if (bridges::cpp_uno::shared::isSimpleType( pTD ))
232 0 : return true;
233 : #if defined(FREEBSD) || defined(NETBSD) || defined(OPENBSD) || \
234 : defined(MACOSX) || defined(DRAGONFLY)
235 : // Only structs of exactly 1, 2, 4, or 8 bytes are returned through
236 : // registers, see <http://developer.apple.com/documentation/DeveloperTools/
237 : // Conceptual/LowLevelABI/Articles/IA32.html>:
238 : if (pTD->eTypeClass == typelib_TypeClass_STRUCT &&
239 : (recursive || pTD->nSize <= 2 || pTD->nSize == 4 || pTD->nSize == 8))
240 : {
241 : typelib_CompoundTypeDescription *const pCompTD =
242 : (typelib_CompoundTypeDescription *) pTD;
243 : for ( sal_Int32 pos = pCompTD->nMembers; pos--; ) {
244 : typelib_TypeDescription * pMemberTD = 0;
245 : TYPELIB_DANGER_GET( &pMemberTD, pCompTD->ppTypeRefs[pos] );
246 : bool const b = isSimpleReturnType(pMemberTD, true);
247 : TYPELIB_DANGER_RELEASE( pMemberTD );
248 : if (! b)
249 : return false;
250 : }
251 : return true;
252 : }
253 : #else
254 : (void)recursive;
255 : #endif
256 0 : return false;
257 : }
258 : }
259 :
260 : namespace bridges { namespace cpp_uno { namespace shared {
261 :
262 0 : void unoInterfaceProxyDispatch(
263 : uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
264 : void * pReturn, void * pArgs[], uno_Any ** ppException )
265 : {
266 : // is my surrogate
267 : bridges::cpp_uno::shared::UnoInterfaceProxy * pThis
268 0 : = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI);
269 :
270 0 : switch (pMemberDescr->eTypeClass)
271 : {
272 : case typelib_TypeClass_INTERFACE_ATTRIBUTE:
273 : {
274 : VtableSlot aVtableSlot(
275 : getVtableSlot(
276 : reinterpret_cast<
277 : typelib_InterfaceAttributeTypeDescription const * >(
278 0 : pMemberDescr)));
279 0 : if (pReturn)
280 : {
281 : // dependent dispatch
282 : cpp_call(
283 : pThis, aVtableSlot,
284 : ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
285 : 0, 0, // no params
286 0 : pReturn, pArgs, ppException );
287 : }
288 : else
289 : {
290 : // is SET
291 : typelib_MethodParameter aParam;
292 : aParam.pTypeRef =
293 0 : ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
294 0 : aParam.bIn = sal_True;
295 0 : aParam.bOut = sal_False;
296 :
297 0 : typelib_TypeDescriptionReference * pReturnTypeRef = 0;
298 0 : OUString aVoidName("void");
299 : typelib_typedescriptionreference_new(
300 0 : &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
301 :
302 : // dependent dispatch
303 0 : aVtableSlot.index += 1; // get, then set method
304 : cpp_call(
305 : pThis, aVtableSlot,
306 : pReturnTypeRef,
307 : 1, &aParam,
308 0 : pReturn, pArgs, ppException );
309 :
310 0 : typelib_typedescriptionreference_release( pReturnTypeRef );
311 : }
312 :
313 0 : break;
314 : }
315 : case typelib_TypeClass_INTERFACE_METHOD:
316 : {
317 : VtableSlot aVtableSlot(
318 : getVtableSlot(
319 : reinterpret_cast<
320 : typelib_InterfaceMethodTypeDescription const * >(
321 0 : pMemberDescr)));
322 0 : switch (aVtableSlot.index)
323 : {
324 : // standard calls
325 : case 1: // acquire uno interface
326 0 : (*pUnoI->acquire)( pUnoI );
327 0 : *ppException = 0;
328 0 : break;
329 : case 2: // release uno interface
330 0 : (*pUnoI->release)( pUnoI );
331 0 : *ppException = 0;
332 0 : break;
333 : case 0: // queryInterface() opt
334 : {
335 0 : typelib_TypeDescription * pTD = 0;
336 0 : TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
337 0 : if (pTD)
338 : {
339 0 : uno_Interface * pInterface = 0;
340 0 : (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)(
341 : pThis->pBridge->getUnoEnv(),
342 0 : (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
343 :
344 0 : if (pInterface)
345 : {
346 : ::uno_any_construct(
347 : reinterpret_cast< uno_Any * >( pReturn ),
348 0 : &pInterface, pTD, 0 );
349 0 : (*pInterface->release)( pInterface );
350 0 : TYPELIB_DANGER_RELEASE( pTD );
351 0 : *ppException = 0;
352 0 : break;
353 : }
354 0 : TYPELIB_DANGER_RELEASE( pTD );
355 : }
356 : } // else perform queryInterface()
357 : default:
358 : // dependent dispatch
359 : cpp_call(
360 : pThis, aVtableSlot,
361 : ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
362 : ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
363 : ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
364 0 : pReturn, pArgs, ppException );
365 : }
366 0 : break;
367 : }
368 : default:
369 : {
370 : ::com::sun::star::uno::RuntimeException aExc(
371 : OUString("illegal member type description!"),
372 0 : ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
373 :
374 0 : Type const & rExcType = ::getCppuType( &aExc );
375 : // binary identical null reference
376 0 : ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
377 : }
378 : }
379 0 : }
380 :
381 : } } }
382 :
383 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|