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>
28 #include <unointerfaceproxy.hxx>
29 #include <vtables.hxx>
31 #include <msvc/except.hxx>
33 using namespace ::com::sun::star
;
38 inline void callVirtualMethod(
39 void * pAdjustedThisPtr
, sal_Int32 nVtableIndex
,
40 void * pRegisterReturn
, typelib_TypeClass eReturnTypeClass
,
41 sal_Int32
* pStackLongs
, sal_Int32 nStackLongs
)
43 // parameter list is mixed list of * and values
44 // reference parameters are pointers
46 assert(pStackLongs
&& pAdjustedThisPtr
);
47 static_assert( (sizeof(void *) == 4) &&
48 (sizeof(sal_Int32
) == 4), "### unexpected size of int!" );
57 shl eax
, 2 // sizeof(sal_Int32) == 4
58 add eax
, pStackLongs
// params stack space
65 mov ecx
, pAdjustedThisPtr
67 mov edx
, [ecx
] // pvft
69 shl eax
, 2 // sizeof(void *) == 4
71 call
[edx
] // interface method call must be __cdecl!!!
74 mov ecx
, eReturnTypeClass
75 cmp ecx
, typelib_TypeClass_VOID
77 mov ebx
, pRegisterReturn
79 cmp ecx
, typelib_TypeClass_LONG
81 cmp ecx
, typelib_TypeClass_UNSIGNED_LONG
83 cmp ecx
, typelib_TypeClass_ENUM
86 cmp ecx
, typelib_TypeClass_BOOLEAN
88 cmp ecx
, typelib_TypeClass_BYTE
91 cmp ecx
, typelib_TypeClass_CHAR
93 cmp ecx
, typelib_TypeClass_SHORT
95 cmp ecx
, typelib_TypeClass_UNSIGNED_SHORT
98 cmp ecx
, typelib_TypeClass_FLOAT
101 cmp ecx
, typelib_TypeClass_DOUBLE
104 cmp ecx
, typelib_TypeClass_HYPER
106 cmp ecx
, typelib_TypeClass_UNSIGNED_HYPER
108 jmp Lcleanup
// no simple type
110 mov byte ptr
[ebx
], al
113 mov word ptr
[ebx
], ax
122 mov dword ptr
[ebx
], eax
123 mov dword ptr
[ebx
+4], edx
126 mov dword ptr
[ebx
], eax
129 // cleanup stack (obsolete though because of function)
131 shl eax
, 2 // sizeof(sal_Int32) == 4
132 add eax
, 4 // this ptr
138 bridges::cpp_uno::shared::UnoInterfaceProxy
* pThis
,
139 bridges::cpp_uno::shared::VtableSlot aVtableSlot
,
140 typelib_TypeDescriptionReference
* pReturnTypeRef
,
142 typelib_MethodParameter
* pParams
,
145 uno_Any
** ppUnoExc
) throw ()
147 // max space for: [complex ret ptr], values|ptr ...
148 char * pCppStack
= (char *)alloca( sizeof(sal_Int32
) + (nParams
* sizeof(sal_Int64
)) );
149 char * pCppStackStart
= pCppStack
;
152 typelib_TypeDescription
* pReturnTD
= nullptr;
153 TYPELIB_DANGER_GET( &pReturnTD
, pReturnTypeRef
);
156 void * pCppReturn
= nullptr; // if != 0 && != pUnoReturn, needs reconversion
160 if (bridges::cpp_uno::shared::isSimpleType( pReturnTD
))
162 pCppReturn
= pUnoReturn
; // direct way for simple types
166 // complex return via ptr
167 pCppReturn
= *(void **)pCppStack
168 = (bridges::cpp_uno::shared::relatesToInterfaceType(
170 ? alloca( pReturnTD
->nSize
)
171 : pUnoReturn
); // direct way
172 pCppStack
+= sizeof(void *);
178 static_assert(sizeof(void *) == sizeof(sal_Int32
), "### unexpected size!");
180 void ** pCppArgs
= (void **)alloca( 3 * sizeof(void *) * nParams
);
181 // indices of values this have to be converted (interface conversion cpp<=>uno)
182 sal_Int32
* pTempIndexes
= (sal_Int32
*)(pCppArgs
+ nParams
);
183 // type descriptions for reconversions
184 typelib_TypeDescription
** pTempParamTD
= (typelib_TypeDescription
**)(pCppArgs
+ (2 * nParams
));
186 sal_Int32 nTempIndexes
= 0;
188 for (int nPos
= 0; nPos
< nParams
; ++nPos
)
190 const typelib_MethodParameter
& rParam
= pParams
[nPos
];
191 typelib_TypeDescription
* pParamTD
= nullptr;
192 TYPELIB_DANGER_GET( &pParamTD
, rParam
.pTypeRef
);
194 if (!rParam
.bOut
&& bridges::cpp_uno::shared::isSimpleType(pParamTD
))
196 ::uno_copyAndConvertData(
197 pCppArgs
[nPos
] = pCppStack
, pUnoArgs
[nPos
], pParamTD
,
198 pThis
->getBridge()->getUno2Cpp() );
200 switch (pParamTD
->eTypeClass
)
202 case typelib_TypeClass_HYPER
:
203 case typelib_TypeClass_UNSIGNED_HYPER
:
204 case typelib_TypeClass_DOUBLE
:
205 pCppStack
+= sizeof(sal_Int32
); // extra long
211 TYPELIB_DANGER_RELEASE( pParamTD
);
213 else // ptr to complex value | ref
215 if (! rParam
.bIn
) // is pure out
217 // C++ out is constructed mem, UNO out is not!
219 *(void **)pCppStack
= pCppArgs
[nPos
] = alloca( pParamTD
->nSize
),
222 // default constructed for C++ call
223 pTempIndexes
[nTempIndexes
] = nPos
;
225 // will be released at reconversion
226 pTempParamTD
[nTempIndexes
++] = pParamTD
;
229 else if (bridges::cpp_uno::shared::relatesToInterfaceType(pParamTD
))
231 ::uno_copyAndConvertData(
232 *(void **)pCppStack
= pCppArgs
[nPos
] = alloca( pParamTD
->nSize
),
233 pUnoArgs
[nPos
], pParamTD
,
234 pThis
->getBridge()->getUno2Cpp() );
236 // has to be reconverted
237 pTempIndexes
[nTempIndexes
] = nPos
;
239 // will be released at reconversion
240 pTempParamTD
[nTempIndexes
++] = pParamTD
;
244 *(void **)pCppStack
= pCppArgs
[nPos
] = pUnoArgs
[nPos
];
246 TYPELIB_DANGER_RELEASE( pParamTD
);
249 pCppStack
+= sizeof(sal_Int32
); // standard parameter length
254 // pCppI is msci this pointer
256 reinterpret_cast< void ** >(pThis
->getCppI()) + aVtableSlot
.offset
,
258 pCppReturn
, pReturnTD
->eTypeClass
,
259 (sal_Int32
*)pCppStackStart
,
260 (pCppStack
- pCppStackStart
) / sizeof(sal_Int32
) );
262 __except (msvc_filterCppException(
263 GetExceptionInformation(),
264 *ppUnoExc
, pThis
->getBridge()->getCpp2Uno() ))
266 // *ppUnoExc was constructed by filter function
268 while (nTempIndexes
--)
270 sal_Int32 nIndex
= pTempIndexes
[nTempIndexes
];
271 // destroy temp C++ param => C++: every param was constructed
273 pCppArgs
[nIndex
], pTempParamTD
[nTempIndexes
],
275 TYPELIB_DANGER_RELEASE( pTempParamTD
[nTempIndexes
] );
280 TYPELIB_DANGER_RELEASE( pReturnTD
);
285 // NO exception occurred
288 // reconvert temporary params
289 while (nTempIndexes
--)
291 int nIndex
= pTempIndexes
[nTempIndexes
];
292 typelib_TypeDescription
* pParamTD
=
293 pTempParamTD
[nTempIndexes
];
295 if (pParams
[nIndex
].bIn
)
297 if (pParams
[nIndex
].bOut
) // inout
300 pUnoArgs
[nIndex
], pParamTD
, nullptr ); // destroy UNO value
301 ::uno_copyAndConvertData(
302 pUnoArgs
[nIndex
], pCppArgs
[nIndex
], pParamTD
,
303 pThis
->getBridge()->getCpp2Uno() );
308 ::uno_copyAndConvertData(
309 pUnoArgs
[nIndex
], pCppArgs
[nIndex
], pParamTD
,
310 pThis
->getBridge()->getCpp2Uno() );
313 // destroy temp C++ param => C++: every param was constructed
315 pCppArgs
[nIndex
], pParamTD
, uno::cpp_release
);
317 TYPELIB_DANGER_RELEASE( pParamTD
);
321 if (pCppReturn
&& pUnoReturn
!= pCppReturn
)
323 ::uno_copyAndConvertData(
324 pUnoReturn
, pCppReturn
, pReturnTD
,
325 pThis
->getBridge()->getCpp2Uno() );
327 pCppReturn
, pReturnTD
, uno::cpp_release
);
332 TYPELIB_DANGER_RELEASE( pReturnTD
);
337 namespace bridges::cpp_uno::shared
{
339 void unoInterfaceProxyDispatch(
340 uno_Interface
* pUnoI
,
341 const typelib_TypeDescription
* pMemberTD
,
344 uno_Any
** ppException
)
347 bridges::cpp_uno::shared::UnoInterfaceProxy
* pThis
348 = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy
* >(pUnoI
);
350 switch (pMemberTD
->eTypeClass
)
352 case typelib_TypeClass_INTERFACE_ATTRIBUTE
:
354 VtableSlot
aVtableSlot(
357 typelib_InterfaceAttributeTypeDescription
const * >(
364 reinterpret_cast<typelib_InterfaceAttributeTypeDescription
const *>(pMemberTD
)->pAttributeTypeRef
,
365 0, nullptr, // no params
366 pReturn
, pArgs
, ppException
);
371 typelib_MethodParameter aParam
;
373 reinterpret_cast<typelib_InterfaceAttributeTypeDescription
const *>(pMemberTD
)->pAttributeTypeRef
;
374 aParam
.bIn
= sal_True
;
375 aParam
.bOut
= sal_False
;
377 typelib_TypeDescriptionReference
* pReturnTypeRef
= nullptr;
378 OUString
aVoidName("void");
379 typelib_typedescriptionreference_new(
380 &pReturnTypeRef
, typelib_TypeClass_VOID
, aVoidName
.pData
);
382 aVtableSlot
.index
+= 1; // get, then set method
387 pReturn
, pArgs
, ppException
);
389 typelib_typedescriptionreference_release( pReturnTypeRef
);
394 case typelib_TypeClass_INTERFACE_METHOD
:
396 VtableSlot
aVtableSlot(
399 typelib_InterfaceMethodTypeDescription
const * >(
402 switch (aVtableSlot
.index
)
404 case 1: // acquire UNO interface
405 (*pUnoI
->acquire
)( pUnoI
);
406 *ppException
= nullptr;
408 case 2: // release UNO interface
409 (*pUnoI
->release
)( pUnoI
);
410 *ppException
= nullptr;
412 case 0: // queryInterface() opt
414 typelib_TypeDescription
* pTD
= nullptr;
415 TYPELIB_DANGER_GET( &pTD
, static_cast< uno::Type
* >( pArgs
[0] )->getTypeLibType() );
419 uno_Interface
* pInterface
= nullptr;
420 (*pThis
->getBridge()->getUnoEnv()->getRegisteredInterface
)(
421 pThis
->getBridge()->getUnoEnv(),
422 reinterpret_cast<void **>(&pInterface
), pThis
->oid
.pData
, reinterpret_cast<typelib_InterfaceTypeDescription
*>(pTD
) );
427 static_cast< uno_Any
* >( pReturn
),
428 &pInterface
, pTD
, nullptr );
429 (*pInterface
->release
)( pInterface
);
430 TYPELIB_DANGER_RELEASE( pTD
);
431 *ppException
= nullptr;
434 TYPELIB_DANGER_RELEASE( pTD
);
436 [[fallthrough
]]; // else perform queryInterface()
439 typelib_InterfaceMethodTypeDescription
const* pMethodTD
440 = reinterpret_cast<typelib_InterfaceMethodTypeDescription
const *>(pMemberTD
);
442 cpp_call(pThis
, aVtableSlot
, pMethodTD
->pReturnTypeRef
, pMethodTD
->nParams
, pMethodTD
->pParams
,
443 pReturn
, pArgs
, ppException
);
449 uno::RuntimeException
aExc("Illegal member type description!", uno::Reference
<uno::XInterface
>());
451 uno::Type
const & rExcType
= cppu::UnoType
<decltype(aExc
)>::get();
452 // binary identical null reference
453 ::uno_type_any_construct(*ppException
, &aExc
, rExcType
.getTypeLibType(), nullptr);
460 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */