LibreOffice Module bridges (master)  1
gcc3_solaris_intel/uno2cpp.cxx
Go to the documentation of this file.
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 #include <sal/config.h>
21 
22 #include <exception>
23 #include <typeinfo>
24 
25 #include <malloc.h>
26 #include <sal/alloca.h>
27 
28 #include <com/sun/star/uno/genfunc.hxx>
29 #include <com/sun/star/uno/Exception.hpp>
30 #include "com/sun/star/uno/RuntimeException.hpp"
32 #include <uno/data.h>
33 
34 #include "bridge.hxx"
35 #include "types.hxx"
36 #include "unointerfaceproxy.hxx"
37 #include "vtables.hxx"
38 
39 #include "share.hxx"
40 
41 #include "callvirtualmethod.hxx"
42 
43 using namespace ::com::sun::star::uno;
44 
45 namespace
46 {
47 
48 static void cpp_call(
51  typelib_TypeDescriptionReference * pReturnTypeRef,
52  sal_Int32 nParams, typelib_MethodParameter * pParams,
53  void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc )
54 {
55  // max space for: [complex ret ptr], values|ptr ...
56  char * pCppStack =
57  (char *)alloca( sizeof(sal_Int32) + ((nParams+2) * sizeof(sal_Int64)) );
58  char * pCppStackStart = pCppStack;
59 
60  // return
61  typelib_TypeDescription * pReturnTypeDescr = 0;
62  TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
63  assert(pReturnTypeDescr);
64 
65  void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion
66 
67  if (pReturnTypeDescr)
68  {
69  if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
70  {
71  pCppReturn = pUnoReturn; // direct way for simple types
72  }
73  else
74  {
75  // complex return via ptr
76  pCppReturn = *(void **)pCppStack
78  pReturnTypeDescr )
79  ? alloca( pReturnTypeDescr->nSize )
80  : pUnoReturn); // direct way
81  pCppStack += sizeof(void *);
82  }
83  }
84  // push this
85  void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI())
86  + aVtableSlot.offset;
87  *(void**)pCppStack = pAdjustedThisPtr;
88  pCppStack += sizeof( void* );
89 
90  // stack space
91  static_assert(sizeof(void *) == sizeof(sal_Int32), "### unexpected size!");
92  // args
93  void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams );
94  // indices of values this have to be converted (interface conversion cpp<=>uno)
95  sal_Int32 * pTempIndices = (sal_Int32 *)(pCppArgs + nParams);
96  // type descriptions for reconversions
97  typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
98 
99  sal_Int32 nTempIndices = 0;
100 
101  for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
102  {
103  const typelib_MethodParameter & rParam = pParams[nPos];
104  typelib_TypeDescription * pParamTypeDescr = 0;
105  TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
106 
107  if (!rParam.bOut
108  && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
109  {
110  uno_copyAndConvertData( pCppArgs[nPos] = pCppStack, pUnoArgs[nPos], pParamTypeDescr,
111  pThis->getBridge()->getUno2Cpp() );
112 
113  switch (pParamTypeDescr->eTypeClass)
114  {
115  case typelib_TypeClass_HYPER:
116  case typelib_TypeClass_UNSIGNED_HYPER:
117  case typelib_TypeClass_DOUBLE:
118  pCppStack += sizeof(sal_Int32); // extra long
119  }
120  // no longer needed
121  TYPELIB_DANGER_RELEASE( pParamTypeDescr );
122  }
123  else // ptr to complex value | ref
124  {
125  if (! rParam.bIn) // is pure out
126  {
127  // cpp out is constructed mem, uno out is not!
129  *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
130  pParamTypeDescr );
131  pTempIndices[nTempIndices] = nPos; // default constructed for cpp call
132  // will be released at reconversion
133  ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
134  }
135  // is in/inout
137  pParamTypeDescr ))
138  {
140  *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
141  pUnoArgs[nPos], pParamTypeDescr,
142  pThis->getBridge()->getUno2Cpp() );
143 
144  pTempIndices[nTempIndices] = nPos; // has to be reconverted
145  // will be released at reconversion
146  ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
147  }
148  else // direct way
149  {
150  *(void **)pCppStack = pCppArgs[nPos] = pUnoArgs[nPos];
151  // no longer needed
152  TYPELIB_DANGER_RELEASE( pParamTypeDescr );
153  }
154  }
155  pCppStack += sizeof(sal_Int32); // standard parameter length
156  }
157 
158  try
159  {
160  assert( !( (pCppStack - pCppStackStart ) & 3) && "UNALIGNED STACK !!! (Please DO panic)");
161  try {
163  pAdjustedThisPtr, aVtableSlot.index,
164  pCppReturn, pReturnTypeDescr->eTypeClass,
165  (sal_Int32 *)pCppStackStart, (pCppStack - pCppStackStart) / sizeof(sal_Int32) );
166  } catch (css::uno::Exception &) {
167  throw;
168  } catch (std::exception & e) {
169  throw css::uno::RuntimeException(
170  "C++ code threw " + o3tl::runtimeToOUString(typeid(e).name()) + ": "
171  + o3tl::runtimeToOUString(e.what()));
172  } catch (...) {
173  throw css::uno::RuntimeException("C++ code threw unknown exception");
174  }
175  // NO exception occurred...
176  *ppUnoExc = 0;
177 
178  // reconvert temporary params
179  for ( ; nTempIndices--; )
180  {
181  sal_Int32 nIndex = pTempIndices[nTempIndices];
182  typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndices];
183 
184  if (pParams[nIndex].bIn)
185  {
186  if (pParams[nIndex].bOut) // inout
187  {
188  uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value
189  uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
190  pThis->getBridge()->getCpp2Uno() );
191  }
192  }
193  else // pure out
194  {
195  uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
196  pThis->getBridge()->getCpp2Uno() );
197  }
198  // destroy temp cpp param => cpp: every param was constructed
199  uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
200 
201  TYPELIB_DANGER_RELEASE( pParamTypeDescr );
202  }
203  // return value
204  if (pCppReturn && pUnoReturn != pCppReturn)
205  {
206  uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr,
207  pThis->getBridge()->getCpp2Uno() );
208  uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release );
209  }
210  }
211  catch (...)
212  {
213  // fill uno exception
215 
216  // temporary params
217  for ( ; nTempIndices--; )
218  {
219  sal_Int32 nIndex = pTempIndices[nTempIndices];
220  // destroy temp cpp param => cpp: every param was constructed
221  uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndices], cpp_release );
222  TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndices] );
223  }
224  // return type
225  if (pReturnTypeDescr)
226  TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
227  }
228 }
229 
230 }
231 
232 namespace bridges::cpp_uno::shared {
233 
235  uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
236  void * pReturn, void * pArgs[], uno_Any ** ppException )
237 {
238  // is my surrogate
240  = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI);
241  typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr;
242 
243  switch (pMemberDescr->eTypeClass)
244  {
245  case typelib_TypeClass_INTERFACE_ATTRIBUTE:
246  {
247  VtableSlot aVtableSlot(
249  reinterpret_cast<
250  typelib_InterfaceAttributeTypeDescription const * >(
251  pMemberDescr)));
252  if (pReturn)
253  {
254  // dependent dispatch
255  cpp_call(
256  pThis, aVtableSlot,
257  ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
258  0, 0, // no params
259  pReturn, pArgs, ppException );
260  }
261  else
262  {
263  // is SET
264  typelib_MethodParameter aParam;
265  aParam.pTypeRef =
266  ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
267  aParam.bIn = sal_True;
268  aParam.bOut = sal_False;
269 
270  typelib_TypeDescriptionReference * pReturnTypeRef = 0;
271  OUString aVoidName("void");
273  &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
274 
275  // dependent dispatch
276  aVtableSlot.index += 1; // get, then set method
277  cpp_call(
278  pThis, aVtableSlot,
279  pReturnTypeRef,
280  1, &aParam,
281  pReturn, pArgs, ppException );
282 
284  }
285 
286  break;
287  }
288  case typelib_TypeClass_INTERFACE_METHOD:
289  {
290  VtableSlot aVtableSlot(
292  reinterpret_cast<
293  typelib_InterfaceMethodTypeDescription const * >(
294  pMemberDescr)));
295  switch (aVtableSlot.index)
296  {
297  // standard calls
298  case 1: // acquire uno interface
299  (*pUnoI->acquire)( pUnoI );
300  *ppException = 0;
301  break;
302  case 2: // release uno interface
303  (*pUnoI->release)( pUnoI );
304  *ppException = 0;
305  break;
306  case 0: // queryInterface() opt
307  {
308  typelib_TypeDescription * pTD = 0;
309  TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
310  if (pTD)
311  {
312  uno_Interface * pInterface = 0;
313  (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)(
314  pThis->pBridge->getUnoEnv(),
315  (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
316 
317  if (pInterface)
318  {
319  ::uno_any_construct(
320  reinterpret_cast< uno_Any * >( pReturn ),
321  &pInterface, pTD, 0 );
322  (*pInterface->release)( pInterface );
323  TYPELIB_DANGER_RELEASE( pTD );
324  *ppException = 0;
325  break;
326  }
327  TYPELIB_DANGER_RELEASE( pTD );
328  }
329  } // else perform queryInterface()
330  default:
331  // dependent dispatch
332  cpp_call(
333  pThis, aVtableSlot,
334  ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
335  ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
336  ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
337  pReturn, pArgs, ppException );
338  }
339  break;
340  }
341  default:
342  {
343  ::com::sun::star::uno::RuntimeException aExc(
344  "illegal member type description!",
346 
347  Type const & rExcType = cppu::UnoType<decltype(aExc)>::get();
348  // binary identical null reference
349  ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
350  }
351  }
352 }
353 
354 }
355 
356 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Type
sal_Int32 nIndex
void SAL_CALL uno_destructData(void *pValue, typelib_TypeDescription *pTypeDescr, uno_ReleaseFunc release) SAL_THROW_EXTERN_C()
Represents a vtable slot of a C++ class.
Definition: vtables.hxx:59
void fillUnoException(uno_Any *pExc, uno_Mapping *pCpp2Uno)
bool isSimpleType(typelib_TypeClass typeClass)
Determines whether a type is a "simple" type (VOID, BOOLEAN, BYTE, SHORT, UNSIGNED SHORT...
Definition: types.cxx:28
void callVirtualMethod(void *pAdjustedThisPtr, sal_Int32 nVtableIndex, void *pRegisterReturn, typelib_TypeDescription *pReturnTypeDescr, bool bSimpleReturn, sal_Int32 *pStackLongs, sal_Int32 nStackLongs)
sal_Int32 index
The index within the vtable.
Definition: vtables.hxx:76
A uno proxy wrapping a cpp interface.
bool relatesToInterfaceType(typelib_TypeDescription const *type)
Determines whether a type relates to an interface type (is itself an interface type, or might contain entities of interface type).
Definition: types.cxx:41
void unoInterfaceProxyDispatch(uno_Interface *pUnoI, const typelib_TypeDescription *pMemberDescr, void *pReturn, void *pArgs[], uno_Any **ppException)
uno_ExtEnvironment * getUnoEnv()
Definition: bridge.hxx:70
struct _uno_Any uno_Any
Definition: msvc/except.hxx:31
uno_Mapping * getUno2Cpp()
Definition: bridge.hxx:73
static void cpp_call(bridges::cpp_uno::shared::UnoInterfaceProxy *pThis, bridges::cpp_uno::shared::VtableSlot aVtableSlot, typelib_TypeDescriptionReference *pReturnTypeRef, sal_Int32 nParams, typelib_MethodParameter *pParams, void *pUnoReturn, void *pUnoArgs[], uno_Any **ppUnoExc)
sal_Int32 offset
The offset of the vtable.
Definition: vtables.hxx:68
typelib_InterfaceTypeDescription * pTypeDescr
void SAL_CALL uno_constructData(void *pMem, typelib_TypeDescription *pTypeDescr) SAL_THROW_EXTERN_C()
#define sal_True
void SAL_CALL uno_copyAndConvertData(void *pDest, void *pSource, typelib_TypeDescription *pTypeDescr, uno_Mapping *mapping) SAL_THROW_EXTERN_C()
void SAL_CALL typelib_typedescriptionreference_release(typelib_TypeDescriptionReference *pRef) SAL_THROW_EXTERN_C()
struct _typelib_TypeDescription typelib_TypeDescription
Definition: msvc/except.hxx:52
uno_Mapping * getCpp2Uno()
Definition: bridge.hxx:72
VtableSlot getVtableSlot(typelib_InterfaceAttributeTypeDescription const *ifcMember)
Calculates the vtable slot associated with an interface attribute member.
Definition: vtables.cxx:132
void SAL_CALL typelib_typedescriptionreference_new(typelib_TypeDescriptionReference **ppTDR, typelib_TypeClass eTypeClass, rtl_uString *pTypeName) SAL_THROW_EXTERN_C()
OUString runtimeToOUString(char const *runtimeString)
#define sal_False
com::sun::star::uno::XInterface * getCppI()
sal_uInt16 nPos
char const * name