LibreOffice Module bridges (master) 1
gcc3_linux_loongarch64/cpp2uno.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
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 <com/sun/star/uno/genfunc.hxx>
21#include <sal/log.hxx>
22#include <typelib/typedescription.hxx>
23#include <uno/data.h>
24#include <osl/endian.h>
25#include "bridge.hxx"
26#include "cppinterfaceproxy.hxx"
27#include "types.hxx"
28#include "vtablefactory.hxx"
29#include "call.hxx"
30#include "share.hxx"
31#include "abi.hxx"
32
33#include <stdio.h>
34#include <string.h>
35#include <typeinfo>
36
37using namespace com::sun::star::uno;
38
40{
42{
43 const typelib_CompoundTypeDescription* p
44 = reinterpret_cast<const typelib_CompoundTypeDescription*>(type);
45 for (sal_Int32 i = 0; i < p->nMembers; ++i)
46 {
47 if (p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_STRUCT
48 || p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_EXCEPTION)
49 {
51 TYPELIB_DANGER_GET(&t, p->ppTypeRefs[i]);
52 bool b = is_complex_struct(t);
53 TYPELIB_DANGER_RELEASE(t);
54 if (b)
55 {
56 return true;
57 }
58 }
59 else if (!bridges::cpp_uno::shared::isSimpleType(p->ppTypeRefs[i]->eTypeClass))
60 return true;
61 }
62 if (p->pBaseTypeDescription != 0)
63 return is_complex_struct(&p->pBaseTypeDescription->aBase);
64 return false;
65}
66
67bool return_in_hidden_param(typelib_TypeDescriptionReference* pTypeRef)
68{
70 return false;
71 else if (pTypeRef->eTypeClass == typelib_TypeClass_STRUCT
72 || pTypeRef->eTypeClass == typelib_TypeClass_EXCEPTION)
73 {
74 typelib_TypeDescription* pTypeDescr = 0;
75 TYPELIB_DANGER_GET(&pTypeDescr, pTypeRef);
76
77 //A Composite Type not larger than 16 bytes is returned in up to two GPRs
78 bool bRet = pTypeDescr->nSize > 16 || is_complex_struct(pTypeDescr);
79
80 TYPELIB_DANGER_RELEASE(pTypeDescr);
81 return bRet;
82 }
83 return true;
84}
85}
86
87namespace
88{
90 const typelib_TypeDescription* pMemberTypeDescr,
91 typelib_TypeDescriptionReference* pReturnTypeRef, // 0 indicates void return
92 sal_Int32 nParams, typelib_MethodParameter* pParams, void** gpreg,
93 void** fpreg, void** ovrflw,
94 sal_uInt64* pRegisterReturn /* space for register return */)
95{
96 sal_Int32 gCount = 0;
97 sal_Int32 fCount = 0;
98 sal_Int32 sp = 0;
99
100 // return
101 typelib_TypeDescription* pReturnTypeDescr = 0;
102 if (pReturnTypeRef)
103 TYPELIB_DANGER_GET(&pReturnTypeDescr, pReturnTypeRef);
104 loongarch64::ReturnKind returnKind
105 = (pReturnTypeRef == nullptr || pReturnTypeRef->eTypeClass == typelib_TypeClass_VOID)
107 : loongarch64::getReturnKind(pReturnTypeRef);
108
109 void* pUnoReturn = 0;
110 void* pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need
111
112 if (pReturnTypeDescr)
113 {
115 {
116 pCppReturn = gpreg[gCount++]; // complex return via ptr (pCppReturn)
117 pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType(pReturnTypeDescr)
118 ? alloca(pReturnTypeDescr->nSize)
119 : pCppReturn); // direct way
120 }
121 else
122 {
123 pUnoReturn = pRegisterReturn; // direct way for simple types
124 }
125 }
126
127 // pop this
128 gCount++;
129
130 // stack space
131 static_assert(sizeof(void*) == sizeof(sal_Int64), "### unexpected size!");
132 // parameters
133 void** pUnoArgs = (void**)alloca(4 * sizeof(void*) * nParams);
134 void** pCppArgs = pUnoArgs + nParams;
135 // indices of values this have to be converted (interface conversion cpp<=>uno)
136 sal_Int32* pTempIndices = (sal_Int32*)(pUnoArgs + (2 * nParams));
137 // type descriptions for reconversions
138 typelib_TypeDescription** ppTempParamTypeDescr
139 = (typelib_TypeDescription**)(pUnoArgs + (3 * nParams));
140
141 sal_Int32 nTempIndices = 0;
142
143 for (sal_Int32 nPos = 0; nPos < nParams; ++nPos)
144 {
145 const typelib_MethodParameter& rParam = pParams[nPos];
146
147 typelib_TypeDescription* pParamTypeDescr = 0;
148 TYPELIB_DANGER_GET(&pParamTypeDescr, rParam.pTypeRef);
149
150 if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType(pParamTypeDescr)) // value
151 {
152 switch (pParamTypeDescr->eTypeClass)
153 {
154 case typelib_TypeClass_FLOAT:
155 case typelib_TypeClass_DOUBLE:
156 pCppArgs[nPos]
157 = fCount != MAX_FP_REGS
158 ? &(fpreg[fCount++])
159 : (gCount != MAX_GP_REGS ? &(gpreg[gCount++]) : &(ovrflw[sp++]));
160 pUnoArgs[nPos] = pCppArgs[nPos];
161 break;
162 default:
163 pCppArgs[nPos] = gCount == MAX_GP_REGS ? &(ovrflw[sp++]) : &(gpreg[gCount++]);
164 pUnoArgs[nPos] = pCppArgs[nPos];
165 break;
166 }
167 // no longer needed
168 TYPELIB_DANGER_RELEASE(pParamTypeDescr);
169 }
170 else // ptr to complex value | ref
171 {
172 void* pCppStack;
173 pCppStack = gCount == MAX_GP_REGS ? ovrflw[sp++] : gpreg[gCount++];
174 pCppArgs[nPos] = pCppStack;
175 if (!rParam.bIn) // is pure out
176 {
177 // uno out is unconstructed mem!
178 pUnoArgs[nPos] = alloca(pParamTypeDescr->nSize);
179 pTempIndices[nTempIndices] = nPos;
180 // will be released at reconversion
181 ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
182 }
183 // is in/inout
184 else if (bridges::cpp_uno::shared::relatesToInterfaceType(pParamTypeDescr))
185 {
186 uno_copyAndConvertData(pUnoArgs[nPos] = alloca(pParamTypeDescr->nSize), pCppStack,
187 pParamTypeDescr, pThis->getBridge()->getCpp2Uno());
188 pTempIndices[nTempIndices] = nPos; // has to be reconverted
189 // will be released at reconversion
190 ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
191 }
192 else // direct way
193 {
194 pUnoArgs[nPos] = pCppStack;
195 // no longer needed
196 TYPELIB_DANGER_RELEASE(pParamTypeDescr);
197 }
198 }
199 }
200 // ExceptionHolder
201 uno_Any aUnoExc; // Any will be constructed by callee
202 uno_Any* pUnoExc = &aUnoExc;
203
204 // invoke uno dispatch call
205 (*pThis->getUnoI()->pDispatcher)(pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs,
206 &pUnoExc);
207 // in case an exception occurred...
208 if (pUnoExc)
209 {
210 // destruct temporary in/inout params
211 for (; nTempIndices--;)
212 {
213 sal_Int32 nIndex = pTempIndices[nTempIndices];
214
215 if (pParams[nIndex].bIn) // is in/inout => was constructed
216 uno_destructData(pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndices], 0);
217 TYPELIB_DANGER_RELEASE(ppTempParamTypeDescr[nTempIndices]);
218 }
219 if (pReturnTypeDescr)
220 TYPELIB_DANGER_RELEASE(pReturnTypeDescr);
221
223 // has to destruct the any
224 // is here for dummy
225 return -1;
226 }
227 else // else no exception occurred...
228 {
229 // temporary params
230 for (; nTempIndices--;)
231 {
232 sal_Int32 nIndex = pTempIndices[nTempIndices];
233 typelib_TypeDescription* pParamTypeDescr = ppTempParamTypeDescr[nTempIndices];
234
235 if (pParams[nIndex].bOut) // inout/out
236 {
237 // convert and assign
238 uno_destructData(pCppArgs[nIndex], pParamTypeDescr, cpp_release);
239 uno_copyAndConvertData(pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
240 pThis->getBridge()->getUno2Cpp());
241 }
242 // destroy temp uno param
243 uno_destructData(pUnoArgs[nIndex], pParamTypeDescr, 0);
244
245 TYPELIB_DANGER_RELEASE(pParamTypeDescr);
246 }
247 // return
248 if (pCppReturn) // has complex return
249 {
250 if (pUnoReturn != pCppReturn) // needs reconversion
251 {
252 uno_copyAndConvertData(pCppReturn, pUnoReturn, pReturnTypeDescr,
253 pThis->getBridge()->getUno2Cpp());
254 // destroy temp uno return
255 uno_destructData(pUnoReturn, pReturnTypeDescr, 0);
256 }
257 // complex return ptr is set to return reg
258 *(void**)pRegisterReturn = pCppReturn;
259 }
260 if (pReturnTypeDescr)
261 {
262 TYPELIB_DANGER_RELEASE(pReturnTypeDescr);
263 }
264 switch (returnKind)
265 {
267 return 0;
269 return 1;
270 default:
271 return -1;
272 }
273 }
274}
275
280int cpp_vtable_call(sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset, void** gpreg, void** fpreg,
281 void** ovrflw, sal_uInt64* pRegisterReturn /* space for register return */)
282{
283 static_assert(sizeof(sal_Int64) == sizeof(void*), "### unexpected!");
284
285 // gpreg: [ret *], this, [other gpr params]
286 // fpreg: [fpr params]
287 // ovrflw: [gpr or fpr params (properly aligned)]
288 void* pThis;
289 if (nFunctionIndex & 0x80000000)
290 {
291 nFunctionIndex &= 0x7fffffff;
292 pThis = gpreg[1];
293 }
294 else
295 {
296 pThis = gpreg[0];
297 }
298 pThis = static_cast<char*>(pThis) - nVtableOffset;
301 typelib_InterfaceTypeDescription* pTypeDescr = pCppI->getTypeDescr();
302
303 if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex)
304 {
305 SAL_WARN("bridges", "illegal " << OUString::unacquired(&pTypeDescr->aBase.pTypeName)
306 << " vtable index " << nFunctionIndex << "/"
307 << pTypeDescr->nMapFunctionIndexToMemberIndex);
308 throw RuntimeException(("illegal " + OUString::unacquired(&pTypeDescr->aBase.pTypeName)
309 + " vtable index " + OUString::number(nFunctionIndex) + "/"
310 + OUString::number(pTypeDescr->nMapFunctionIndexToMemberIndex)),
311 (XInterface*)pThis);
312 }
313
314 // determine called method
315 sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
316 assert(nMemberPos < pTypeDescr->nAllMembers);
317
318 TypeDescription aMemberDescr(pTypeDescr->ppAllMembers[nMemberPos]);
319
320 int eRet;
321 switch (aMemberDescr.get()->eTypeClass)
322 {
323 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
324 {
325 typelib_TypeDescriptionReference* pAttrTypeRef
326 = reinterpret_cast<typelib_InterfaceAttributeTypeDescription*>(aMemberDescr.get())
327 ->pAttributeTypeRef;
328
329 if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex)
330 {
331 // is GET method
332 eRet = cpp2uno_call(pCppI, aMemberDescr.get(), pAttrTypeRef, 0, 0, // no params
333 gpreg, fpreg, ovrflw, pRegisterReturn);
334 }
335 else
336 {
337 // is SET method
338 typelib_MethodParameter aParam;
339 aParam.pTypeRef = pAttrTypeRef;
340 aParam.bIn = sal_True;
341 aParam.bOut = sal_False;
342
343 eRet = cpp2uno_call(pCppI, aMemberDescr.get(),
344 0, // indicates void return
345 1, &aParam, gpreg, fpreg, ovrflw, pRegisterReturn);
346 }
347 break;
348 }
349 case typelib_TypeClass_INTERFACE_METHOD:
350 {
351 // is METHOD
352 switch (nFunctionIndex)
353 {
354 case 1: // acquire()
355 pCppI->acquireProxy(); // non virtual call!
356 eRet = -1;
357 break;
358 case 2: // release()
359 pCppI->releaseProxy(); // non virtual call!
360 eRet = -1;
361 break;
362 case 0: // queryInterface() opt
363 {
365 TYPELIB_DANGER_GET(&pTD, reinterpret_cast<Type*>(gpreg[2])->getTypeLibType());
366 if (pTD)
367 {
368 XInterface* pInterface = 0;
369 (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)(
370 pCppI->getBridge()->getCppEnv(), (void**)&pInterface,
371 pCppI->getOid().pData,
372 reinterpret_cast<typelib_InterfaceTypeDescription*>(pTD));
373
374 if (pInterface)
375 {
376 ::uno_any_construct(reinterpret_cast<uno_Any*>(gpreg[0]), &pInterface,
377 pTD, cpp_acquire);
378
379 pInterface->release();
380 TYPELIB_DANGER_RELEASE(pTD);
381
382 reinterpret_cast<void**>(pRegisterReturn)[0] = gpreg[0];
383 eRet = -1;
384 break;
385 }
386 TYPELIB_DANGER_RELEASE(pTD);
387 }
388 } // else perform queryInterface()
389 default:
390 typelib_InterfaceMethodTypeDescription* pMethodTD
391 = reinterpret_cast<typelib_InterfaceMethodTypeDescription*>(
392 aMemberDescr.get());
393
394 eRet = cpp2uno_call(pCppI, aMemberDescr.get(), pMethodTD->pReturnTypeRef,
395 pMethodTD->nParams, pMethodTD->pParams, gpreg, fpreg,
396 ovrflw, pRegisterReturn);
397 }
398 break;
399 }
400 default:
401 {
402 throw RuntimeException("no member description found!", (XInterface*)pThis);
403 }
404 }
405
406 return eRet;
407}
408
409extern "C" void privateSnippetExecutor(...);
410
411int const codeSnippetSize = 0x34;
412
413unsigned char* codeSnippet(unsigned char* code, sal_Int32 functionIndex, sal_Int32 vtableOffset,
414 bool bHasHiddenParam)
415{
416 if (bHasHiddenParam)
417 functionIndex |= 0x80000000;
418
419 unsigned int* p = (unsigned int*)code;
420
421 assert((((unsigned long)code) & 0x3) == 0); //aligned to 4 otherwise a mistake
422
423 /* generate this code */
424 /*
425 # index
426 0: 14000012 lu12i.w $t6,0x0
427 4: 34420000 ori $t6,$t6,0x0
428 # privateSnippetExecutor
429 8: 14000014 lu12i.w $t8,0x0
430 c: 03800294 ori $t8,$t8,0x0
431 10: 16000014 lu32i.d $t8,0x0
432 14: 03000294 lu52i.d $t8,$t8,0x0
433 # cpp_vtable_call
434 18: 14000011 lu12i.w $t5,0x0
435 1c: 03800231 ori $t5,$t5,0x0
436 20: 16000011 lu32i.d $t5,0x0
437 24: 03000231 lu52i.d $t5,$t5,0x0
438 # offset
439 28: 14000013 lu12i.w $t7,0x0
440 2c: 03800273 ori $t7,$t7,0x0
441 30: 4c000280 jr $t8
442 */
443
444 *p++ = 0x14000012 | (((functionIndex >> 12) & 0x000fffff) << 5);
445 *p++ = 0x03800252 | ((functionIndex & 0x00000fff) << 10);
446 *p++ = 0x14000014 | (((((unsigned long)privateSnippetExecutor) >> 12) & 0x000fffff) << 5);
447 *p++ = 0x03800294 | ((((unsigned long)privateSnippetExecutor) & 0x00000fff) << 10);
448 *p++ = 0x16000014 | (((((unsigned long)privateSnippetExecutor) >> 32) & 0x000fffff) << 5);
449 *p++ = 0x03000294 | (((((unsigned long)privateSnippetExecutor) >> 52) & 0x00000fff) << 10);
450 *p++ = 0x14000011 | (((((unsigned long)cpp_vtable_call) >> 12) & 0x000fffff) << 5);
451 *p++ = 0x03800231 | ((((unsigned long)cpp_vtable_call) & 0x00000fff) << 10);
452 *p++ = 0x16000011 | (((((unsigned long)cpp_vtable_call) >> 32) & 0x000fffff) << 5);
453 *p++ = 0x03000231 | (((((unsigned long)cpp_vtable_call) >> 52) & 0x00000fff) << 10);
454 *p++ = 0x14000013 | (((vtableOffset >> 12) & 0x000fffff) << 5);
455 *p++ = 0x03800273 | ((vtableOffset & 0x00000fff) << 10);
456 *p++ = 0x4c000280;
457 return (code + codeSnippetSize);
458}
459}
460
461void bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const* bptr,
462 unsigned char const* eptr)
463{
464 asm volatile("ibar 0" :::);
465}
466
468{
469 void const* fn;
470};
471
474{
475 return static_cast<Slot*>(block) + 2;
476}
477
478std::size_t bridges::cpp_uno::shared::VtableFactory::getBlockSize(sal_Int32 slotCount)
479{
480 return (slotCount + 2) * sizeof(Slot) + slotCount * codeSnippetSize;
481}
482
483namespace
484{
485// Some dummy type whose RTTI is used in the synthesized proxy vtables to make uses of dynamic_cast
486// on such proxy objects not crash:
487struct ProxyRtti
488{
489};
490}
491
493bridges::cpp_uno::shared::VtableFactory::initializeBlock(void* block, sal_Int32 slotCount,
494 sal_Int32,
495 typelib_InterfaceTypeDescription*)
496{
497 Slot* slots = mapBlockToVtable(block);
498 slots[-2].fn = 0; //null
499 slots[-1].fn = &typeid(ProxyRtti);
500 return slots + slotCount;
501}
502
504 Slot** slots, unsigned char* code, sal_PtrDiff writetoexecdiff,
505 typelib_InterfaceTypeDescription const* type, sal_Int32 functionOffset, sal_Int32 functionCount,
506 sal_Int32 vtableOffset)
507{
508 (*slots) -= functionCount;
509 Slot* s = *slots;
510
511 for (sal_Int32 i = 0; i < type->nMembers; ++i)
512 {
513 typelib_TypeDescription* member = 0;
514 TYPELIB_DANGER_GET(&member, type->ppMembers[i]);
515 assert(member != 0);
516 switch (member->eTypeClass)
517 {
518 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
519 // Getter:
520 (s++)->fn = code + writetoexecdiff;
522 code, functionOffset++, vtableOffset,
524 reinterpret_cast<typelib_InterfaceAttributeTypeDescription*>(member)
525 ->pAttributeTypeRef));
526
527 // Setter:
528 if (!reinterpret_cast<typelib_InterfaceAttributeTypeDescription*>(member)
529 ->bReadOnly)
530 {
531 (s++)->fn = code + writetoexecdiff;
532 code = codeSnippet(code, functionOffset++, vtableOffset, false);
533 }
534 break;
535
536 case typelib_TypeClass_INTERFACE_METHOD:
537 (s++)->fn = code + writetoexecdiff;
539 code, functionOffset++, vtableOffset,
541 reinterpret_cast<typelib_InterfaceMethodTypeDescription*>(member)
542 ->pReturnTypeRef));
543 break;
544
545 default:
546 assert(false);
547 break;
548 }
549 TYPELIB_DANGER_RELEASE(member);
550 }
551 return code;
552}
553
554/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
XPropertyListType t
uno_Mapping * getUno2Cpp()
Definition: bridge.hxx:73
uno_ExtEnvironment * getCppEnv()
Definition: bridge.hxx:69
uno_Mapping * getCpp2Uno()
Definition: bridge.hxx:72
A cpp proxy wrapping a uno interface.
static CppInterfaceProxy * castInterfaceToProxy(void *pInterface)
typelib_InterfaceTypeDescription * getTypeDescr()
static Slot * mapBlockToVtable(void *block)
Given a pointer to a block, turn it into a vtable pointer.
static void flushCode(unsigned char const *begin, unsigned char const *end)
Flush all the generated code snippets of a vtable, on platforms that require it.
static unsigned char * addLocalFunctions(Slot **slots, unsigned char *code, sal_PtrDiff writetoexecdiff, typelib_InterfaceTypeDescription const *type, sal_Int32 functionOffset, sal_Int32 functionCount, sal_Int32 vtableOffset)
Fill the vtable slots corresponding to all local (i.e., not inherited) functions of a given interface...
static Slot * initializeBlock(void *block, sal_Int32 slotCount, sal_Int32 vtableNumber, typelib_InterfaceTypeDescription *type)
Initialize a raw vtable block.
static std::size_t getBlockSize(sal_Int32 slotCount)
Calculate the size of a raw vtable block.
void SAL_CALL uno_destructData(void *pValue, typelib_TypeDescription *pTypeDescr, uno_ReleaseFunc release) SAL_THROW_EXTERN_C()
void SAL_CALL uno_copyAndConvertData(void *pDest, void *pSource, typelib_TypeDescription *pTypeDescr, uno_Mapping *mapping) SAL_THROW_EXTERN_C()
void cpp_vtable_call(sal_Int32 func, sal_Int32 offset, void **pStack)
is called on incoming vtable calls (called by asm snippets)
void(* privateSnippetExecutor)()
#define MAX_FP_REGS
#define MAX_GP_REGS
const int codeSnippetSize
static unsigned char * codeSnippet(unsigned char *code, sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset, bool bHasHiddenParam)
static int cpp2uno_call(bridges::cpp_uno::shared::CppInterfaceProxy *pThis, const typelib_TypeDescription *pMemberTypeDescr, typelib_TypeDescriptionReference *pReturnTypeRef, sal_Int32 nParams, typelib_MethodParameter *pParams, void **gpreg, void **fpreg, void **ovrflw, sal_uInt64 *pRegisterReturn)
sal_Int32 nIndex
void * p
sal_uInt16 nPos
#define SAL_WARN(area, stream)
struct _typelib_TypeDescription typelib_TypeDescription
Definition: msvc/except.hxx:53
struct _uno_Any uno_Any
Definition: msvc/except.hxx:32
bool return_in_hidden_param(typelib_TypeDescriptionReference *pTypeRef)
void raiseException(uno_Any *pUnoExc, uno_Mapping *pUno2Cpp)
bool is_complex_struct(const typelib_TypeDescription *type)
bool isSimpleType(typelib_TypeClass typeClass)
Determines whether a type is a "simple" type (VOID, BOOLEAN, BYTE, SHORT, UNSIGNED SHORT,...
Definition: types.cxx:28
bool relatesToInterfaceType(typelib_TypeDescription const *type)
Determines whether a type relates to an interface type (is itself an interface type,...
Definition: types.cxx:41
Type
int i
ReturnKind getReturnKind(typelib_TypeDescriptionReference *type)
sal_Unicode code
#define sal_True
#define sal_False
ResultType type