1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
23 #include <com/sun/star/uno/genfunc.hxx>
24 #include <com/sun/star/uno/RuntimeException.hpp>
25 #include <o3tl/runtimetooustring.hxx>
30 #include <unointerfaceproxy.hxx>
31 #include <vtables.hxx>
34 #include "callvirtualmethod.hxx"
37 using namespace ::com::sun::star::uno
;
41 // Functions for easier insertion of values to registers or stack
42 // pSV - pointer to the source
43 // nr - order of the value [will be increased if stored to register]
44 // pFPR, pGPR - pointer to the registers
45 // pDS - pointer to the stack [will be increased if stored here]
47 // The value in %xmm register is already prepared to be retrieved as a float,
48 // thus we treat float and double the same
49 void INSERT_FLOAT_DOUBLE(
50 void const * pSV
, sal_uInt32
& nr
, double * pFPR
, sal_uInt64
*& pDS
)
52 if ( nr
< x86_64::MAX_SSE_REGS
)
53 pFPR
[nr
++] = *static_cast<double const *>( pSV
);
55 *pDS
++ = *static_cast<sal_uInt64
const *>( pSV
); // verbatim!
59 void const * pSV
, sal_uInt32
& nr
, sal_uInt64
* pGPR
, sal_uInt64
*& pDS
)
61 if ( nr
< x86_64::MAX_GPR_REGS
)
62 pGPR
[nr
++] = *static_cast<sal_uInt64
const *>( pSV
);
64 *pDS
++ = *static_cast<sal_uInt64
const *>( pSV
);
68 void const * pSV
, sal_uInt32
& nr
, sal_uInt64
* pGPR
, sal_uInt64
*& pDS
)
70 if ( nr
< x86_64::MAX_GPR_REGS
)
71 pGPR
[nr
++] = *static_cast<sal_uInt32
const *>( pSV
);
73 *pDS
++ = *static_cast<sal_uInt32
const *>( pSV
);
77 void const * pSV
, sal_uInt32
& nr
, sal_uInt64
* pGPR
, sal_uInt64
*& pDS
)
79 if ( nr
< x86_64::MAX_GPR_REGS
)
80 pGPR
[nr
++] = *static_cast<sal_uInt16
const *>( pSV
);
82 *pDS
++ = *static_cast<sal_uInt16
const *>( pSV
);
86 void const * pSV
, sal_uInt32
& nr
, sal_uInt64
* pGPR
, sal_uInt64
*& pDS
)
88 if ( nr
< x86_64::MAX_GPR_REGS
)
89 pGPR
[nr
++] = *static_cast<sal_uInt8
const *>( pSV
);
91 *pDS
++ = *static_cast<sal_uInt8
const *>( pSV
);
97 bridges::cpp_uno::shared::UnoInterfaceProxy
* pThis
,
98 bridges::cpp_uno::shared::VtableSlot aVtableSlot
,
99 typelib_TypeDescriptionReference
* pReturnTypeRef
,
100 sal_Int32 nParams
, typelib_MethodParameter
* pParams
,
101 void * pUnoReturn
, void * pUnoArgs
[], uno_Any
** ppUnoExc
)
103 // Maximum space for [complex ret ptr], values | ptr ...
104 // (but will be used less - some of the values will be in pGPR and pFPR)
105 sal_uInt64
*pStack
= static_cast<sal_uInt64
*>(__builtin_alloca( (nParams
+ 3) * sizeof(sal_uInt64
) ));
106 sal_uInt64
*pStackStart
= pStack
;
108 sal_uInt64 pGPR
[x86_64::MAX_GPR_REGS
];
111 double pFPR
[x86_64::MAX_SSE_REGS
];
115 typelib_TypeDescription
* pReturnTypeDescr
= nullptr;
116 TYPELIB_DANGER_GET( &pReturnTypeDescr
, pReturnTypeRef
);
117 assert(pReturnTypeDescr
);
119 void * pCppReturn
= nullptr; // if != 0 && != pUnoReturn, needs reconversion (see below)
121 bool bSimpleReturn
= true;
122 if ( pReturnTypeDescr
)
124 if ( x86_64::return_in_hidden_param( pReturnTypeRef
) )
125 bSimpleReturn
= false;
128 pCppReturn
= pUnoReturn
; // direct way for simple types
131 // complex return via ptr
132 pCppReturn
= bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr
)?
133 __builtin_alloca( pReturnTypeDescr
->nSize
) : pUnoReturn
;
134 INSERT_INT64( &pCppReturn
, nGPR
, pGPR
, pStack
);
138 // Push "this" pointer
139 void * pAdjustedThisPtr
= reinterpret_cast< void ** >( pThis
->getCppI() ) + aVtableSlot
.offset
;
140 INSERT_INT64( &pAdjustedThisPtr
, nGPR
, pGPR
, pStack
);
143 void ** pCppArgs
= static_cast<void **>(alloca( 3 * sizeof(void *) * nParams
));
144 // Indices of values this have to be converted (interface conversion cpp<=>uno)
145 sal_Int32
* pTempIndices
= reinterpret_cast<sal_Int32
*>(pCppArgs
+ nParams
);
146 // Type descriptions for reconversions
147 typelib_TypeDescription
** ppTempParamTypeDescr
= reinterpret_cast<typelib_TypeDescription
**>(pCppArgs
+ (2 * nParams
));
149 sal_Int32 nTempIndices
= 0;
151 for ( sal_Int32 nPos
= 0; nPos
< nParams
; ++nPos
)
153 const typelib_MethodParameter
& rParam
= pParams
[nPos
];
154 typelib_TypeDescription
* pParamTypeDescr
= nullptr;
155 TYPELIB_DANGER_GET( &pParamTypeDescr
, rParam
.pTypeRef
);
157 if (!rParam
.bOut
&& bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr
))
159 pCppArgs
[nPos
] = alloca( 8 );
160 uno_copyAndConvertData( pCppArgs
[nPos
], pUnoArgs
[nPos
], pParamTypeDescr
,
161 pThis
->getBridge()->getUno2Cpp() );
163 switch (pParamTypeDescr
->eTypeClass
)
165 case typelib_TypeClass_HYPER
:
166 case typelib_TypeClass_UNSIGNED_HYPER
:
167 INSERT_INT64( pCppArgs
[nPos
], nGPR
, pGPR
, pStack
);
169 case typelib_TypeClass_LONG
:
170 case typelib_TypeClass_UNSIGNED_LONG
:
171 case typelib_TypeClass_ENUM
:
172 INSERT_INT32( pCppArgs
[nPos
], nGPR
, pGPR
, pStack
);
174 case typelib_TypeClass_SHORT
:
175 case typelib_TypeClass_CHAR
:
176 case typelib_TypeClass_UNSIGNED_SHORT
:
177 INSERT_INT16( pCppArgs
[nPos
], nGPR
, pGPR
, pStack
);
179 case typelib_TypeClass_BOOLEAN
:
180 case typelib_TypeClass_BYTE
:
181 INSERT_INT8( pCppArgs
[nPos
], nGPR
, pGPR
, pStack
);
183 case typelib_TypeClass_FLOAT
:
184 case typelib_TypeClass_DOUBLE
:
185 INSERT_FLOAT_DOUBLE( pCppArgs
[nPos
], nFPR
, pFPR
, pStack
);
192 TYPELIB_DANGER_RELEASE( pParamTypeDescr
);
194 else // ptr to complex value | ref
196 if (! rParam
.bIn
) // is pure out
198 // cpp out is constructed mem, uno out is not!
199 pCppArgs
[nPos
] = alloca( pParamTypeDescr
->nSize
);
200 uno_constructData( pCppArgs
[nPos
], pParamTypeDescr
);
201 pTempIndices
[nTempIndices
] = nPos
; // default constructed for cpp call
202 // will be released at reconversion
203 ppTempParamTypeDescr
[nTempIndices
++] = pParamTypeDescr
;
206 else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr
))
208 pCppArgs
[nPos
] = alloca( pParamTypeDescr
->nSize
);
209 uno_copyAndConvertData(
210 pCppArgs
[nPos
], pUnoArgs
[nPos
], pParamTypeDescr
, pThis
->getBridge()->getUno2Cpp() );
212 pTempIndices
[nTempIndices
] = nPos
; // has to be reconverted
213 // will be released at reconversion
214 ppTempParamTypeDescr
[nTempIndices
++] = pParamTypeDescr
;
218 pCppArgs
[nPos
] = pUnoArgs
[nPos
];
220 TYPELIB_DANGER_RELEASE( pParamTypeDescr
);
222 INSERT_INT64( &(pCppArgs
[nPos
]), nGPR
, pGPR
, pStack
);
229 CPPU_CURRENT_NAMESPACE::callVirtualMethod(
230 pAdjustedThisPtr
, aVtableSlot
.index
,
231 pCppReturn
, pReturnTypeRef
, bSimpleReturn
,
232 pStackStart
, ( pStack
- pStackStart
),
234 } catch (const Exception
&) {
236 } catch (const std::exception
& e
) {
237 throw RuntimeException(
238 "C++ code threw " + o3tl::runtimeToOUString(typeid(e
).name())
239 + ": " + o3tl::runtimeToOUString(e
.what()));
241 throw RuntimeException(u
"C++ code threw unknown exception"_ustr
);
246 // reconvert temporary params
247 for ( ; nTempIndices
--; )
249 sal_Int32 nIndex
= pTempIndices
[nTempIndices
];
250 typelib_TypeDescription
* pParamTypeDescr
= ppTempParamTypeDescr
[nTempIndices
];
252 if (pParams
[nIndex
].bIn
)
254 if (pParams
[nIndex
].bOut
) // inout
256 uno_destructData( pUnoArgs
[nIndex
], pParamTypeDescr
, nullptr ); // destroy uno value
257 uno_copyAndConvertData( pUnoArgs
[nIndex
], pCppArgs
[nIndex
], pParamTypeDescr
,
258 pThis
->getBridge()->getCpp2Uno() );
263 uno_copyAndConvertData( pUnoArgs
[nIndex
], pCppArgs
[nIndex
], pParamTypeDescr
,
264 pThis
->getBridge()->getCpp2Uno() );
266 // destroy temp cpp param => cpp: every param was constructed
267 uno_destructData( pCppArgs
[nIndex
], pParamTypeDescr
, cpp_release
);
269 TYPELIB_DANGER_RELEASE( pParamTypeDescr
);
272 if (pCppReturn
&& pUnoReturn
!= pCppReturn
)
274 uno_copyAndConvertData( pUnoReturn
, pCppReturn
, pReturnTypeDescr
,
275 pThis
->getBridge()->getCpp2Uno() );
276 uno_destructData( pCppReturn
, pReturnTypeDescr
, cpp_release
);
281 // fill uno exception
282 CPPU_CURRENT_NAMESPACE::fillUnoException(*ppUnoExc
, pThis
->getBridge()->getCpp2Uno());
285 for ( ; nTempIndices
--; )
287 sal_Int32 nIndex
= pTempIndices
[nTempIndices
];
288 // destroy temp cpp param => cpp: every param was constructed
289 uno_destructData( pCppArgs
[nIndex
], ppTempParamTypeDescr
[nTempIndices
], cpp_release
);
290 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr
[nTempIndices
] );
293 if (pReturnTypeDescr
)
294 TYPELIB_DANGER_RELEASE( pReturnTypeDescr
);
299 namespace bridges::cpp_uno::shared
{
301 void unoInterfaceProxyDispatch(
302 uno_Interface
* pUnoI
, const typelib_TypeDescription
* pMemberDescr
,
303 void * pReturn
, void * pArgs
[], uno_Any
** ppException
)
306 bridges::cpp_uno::shared::UnoInterfaceProxy
* pThis
307 = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy
* >(pUnoI
);
309 switch (pMemberDescr
->eTypeClass
)
311 case typelib_TypeClass_INTERFACE_ATTRIBUTE
:
314 (reinterpret_cast<typelib_InterfaceMemberTypeDescription
const *>(pMemberDescr
)
316 < pThis
->pTypeDescr
->nAllMembers
);
317 VtableSlot
aVtableSlot(
320 typelib_InterfaceAttributeTypeDescription
const * >(
325 // dependent dispatch
328 reinterpret_cast<typelib_InterfaceAttributeTypeDescription
const *>(pMemberDescr
)->pAttributeTypeRef
,
329 0, nullptr, // no params
330 pReturn
, pArgs
, ppException
);
335 typelib_MethodParameter aParam
;
337 reinterpret_cast<typelib_InterfaceAttributeTypeDescription
const *>(pMemberDescr
)->pAttributeTypeRef
;
341 typelib_TypeDescriptionReference
* pReturnTypeRef
= nullptr;
342 OUString
aVoidName(u
"void"_ustr
);
343 typelib_typedescriptionreference_new(
344 &pReturnTypeRef
, typelib_TypeClass_VOID
, aVoidName
.pData
);
346 // dependent dispatch
347 aVtableSlot
.index
+= 1; // get, then set method
349 pThis
, aVtableSlot
, // get, then set method
352 pReturn
, pArgs
, ppException
);
354 typelib_typedescriptionreference_release( pReturnTypeRef
);
359 case typelib_TypeClass_INTERFACE_METHOD
:
362 (reinterpret_cast<typelib_InterfaceMemberTypeDescription
const *>(pMemberDescr
)
364 < pThis
->pTypeDescr
->nAllMembers
);
365 VtableSlot
aVtableSlot(
368 typelib_InterfaceMethodTypeDescription
const * >(
371 switch (aVtableSlot
.index
)
374 case 1: // acquire uno interface
375 (*pUnoI
->acquire
)( pUnoI
);
376 *ppException
= nullptr;
378 case 2: // release uno interface
379 (*pUnoI
->release
)( pUnoI
);
380 *ppException
= nullptr;
382 case 0: // queryInterface() opt
384 typelib_TypeDescription
* pTD
= nullptr;
385 TYPELIB_DANGER_GET( &pTD
, static_cast< Type
* >( pArgs
[0] )->getTypeLibType() );
388 uno_Interface
* pInterface
= nullptr;
389 (*pThis
->getBridge()->getUnoEnv()->getRegisteredInterface
)(
390 pThis
->getBridge()->getUnoEnv(),
391 reinterpret_cast<void **>(&pInterface
), pThis
->oid
.pData
, reinterpret_cast<typelib_InterfaceTypeDescription
*>(pTD
) );
396 static_cast< uno_Any
* >( pReturn
),
397 &pInterface
, pTD
, nullptr );
398 (*pInterface
->release
)( pInterface
);
399 TYPELIB_DANGER_RELEASE( pTD
);
400 *ppException
= nullptr;
403 TYPELIB_DANGER_RELEASE( pTD
);
405 [[fallthrough
]]; // else perform queryInterface()
408 // dependent dispatch
411 reinterpret_cast<typelib_InterfaceMethodTypeDescription
const *>(pMemberDescr
)->pReturnTypeRef
,
412 reinterpret_cast<typelib_InterfaceMethodTypeDescription
const *>(pMemberDescr
)->nParams
,
413 reinterpret_cast<typelib_InterfaceMethodTypeDescription
const *>(pMemberDescr
)->pParams
,
414 pReturn
, pArgs
, ppException
);
420 ::com::sun::star::uno::RuntimeException
aExc(
421 u
"illegal member type description!"_ustr
,
422 ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
>() );
424 Type
const & rExcType
= cppu::UnoType
<decltype(aExc
)>::get();
425 // binary identical null reference
426 ::uno_type_any_construct( *ppException
, &aExc
, rExcType
.getTypeLibType(), nullptr );
433 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */