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 <sal/log.hxx>
24 #include <uno/dispatcher.h>
25 #include <typelib/typedescription.hxx>
28 using namespace com::sun::star
;
30 static bool relatesToInterface(typelib_TypeDescription
* pTypeDescr
)
32 switch (pTypeDescr
->eTypeClass
)
34 // case typelib_TypeClass_TYPEDEF:
35 case typelib_TypeClass_SEQUENCE
:
37 switch (reinterpret_cast<typelib_IndirectTypeDescription
*>(pTypeDescr
)->pType
->eTypeClass
)
39 case typelib_TypeClass_INTERFACE
:
40 case typelib_TypeClass_ANY
: // might relate to interface
42 case typelib_TypeClass_SEQUENCE
:
43 case typelib_TypeClass_STRUCT
:
44 case typelib_TypeClass_EXCEPTION
:
46 typelib_TypeDescription
* pTD
= nullptr;
47 TYPELIB_DANGER_GET( &pTD
, reinterpret_cast<typelib_IndirectTypeDescription
*>(pTypeDescr
)->pType
);
48 bool bRel
= relatesToInterface( pTD
);
49 TYPELIB_DANGER_RELEASE( pTD
);
57 case typelib_TypeClass_STRUCT
:
58 case typelib_TypeClass_EXCEPTION
:
60 // ...optimized... to avoid getDescription() calls!
61 typelib_CompoundTypeDescription
* pComp
= reinterpret_cast<typelib_CompoundTypeDescription
*>(pTypeDescr
);
62 typelib_TypeDescriptionReference
** pTypes
= pComp
->ppTypeRefs
;
63 for ( sal_Int32 nPos
= pComp
->nMembers
; nPos
--; )
65 switch (pTypes
[nPos
]->eTypeClass
)
67 case typelib_TypeClass_INTERFACE
:
68 case typelib_TypeClass_ANY
: // might relate to interface
70 // case typelib_TypeClass_TYPEDEF:
71 case typelib_TypeClass_SEQUENCE
:
72 case typelib_TypeClass_STRUCT
:
73 case typelib_TypeClass_EXCEPTION
:
75 typelib_TypeDescription
* pTD
= nullptr;
76 TYPELIB_DANGER_GET( &pTD
, pTypes
[nPos
] );
77 bool bRel
= relatesToInterface( pTD
);
78 TYPELIB_DANGER_RELEASE( pTD
);
87 if (pComp
->pBaseTypeDescription
)
88 return relatesToInterface( &pComp
->pBaseTypeDescription
->aBase
);
91 case typelib_TypeClass_ANY
: // might relate to interface
92 case typelib_TypeClass_INTERFACE
:
101 extern "C" { static void s_Proxy_dispatch(
102 uno_Interface
* pUnoI
,
103 typelib_TypeDescription
const * pMemberType
,
106 uno_Any
** ppException
) noexcept
108 Proxy
* pThis
= static_cast<Proxy
*>(pUnoI
);
110 typelib_MethodParameter param
;
111 sal_Int32 nParams
= 0;
112 typelib_MethodParameter
* pParams
= nullptr;
113 typelib_TypeDescriptionReference
* pReturnTypeRef
= nullptr;
114 // sal_Int32 nOutParams = 0;
116 switch (pMemberType
->eTypeClass
)
118 case typelib_TypeClass_INTERFACE_ATTRIBUTE
:
122 reinterpret_cast<typelib_InterfaceAttributeTypeDescription
const *>(
123 pMemberType
)->pAttributeTypeRef
;
129 param
.pTypeRef
= reinterpret_cast<typelib_InterfaceAttributeTypeDescription
const *>(
130 pMemberType
)->pAttributeTypeRef
;
137 case typelib_TypeClass_INTERFACE_METHOD
:
139 typelib_InterfaceMethodTypeDescription
const * method_td
=
140 reinterpret_cast<typelib_InterfaceMethodTypeDescription
const *>(pMemberType
);
141 pReturnTypeRef
= method_td
->pReturnTypeRef
;
142 nParams
= method_td
->nParams
;
143 pParams
= method_td
->pParams
;
147 OSL_FAIL( "### illegal member typeclass!" );
151 pThis
->dispatch( pReturnTypeRef
,
160 extern "C" void Proxy_free(SAL_UNUSED_PARAMETER uno_ExtEnvironment
* /*pEnv*/, void * pProxy
) noexcept
162 Proxy
* pThis
= static_cast<Proxy
* >(static_cast<uno_Interface
*>(pProxy
));
167 static void s_Proxy_acquire(uno_Interface
* pUnoI
) noexcept
169 Proxy
* pProxy
= static_cast<Proxy
*>(pUnoI
);
173 static void s_Proxy_release(uno_Interface
* pUnoI
) noexcept
175 Proxy
* pProxy
= static_cast<Proxy
*>(pUnoI
);
179 static void s_acquireAndRegister_v(va_list * pParam
)
181 uno_Interface
* pUnoI
= va_arg(*pParam
, uno_Interface
*);
182 rtl_uString
* pOid
= va_arg(*pParam
, rtl_uString
*);
183 typelib_InterfaceTypeDescription
* pTypeDescr
= va_arg(*pParam
, typelib_InterfaceTypeDescription
*);
184 uno_ExtEnvironment
* pEnv
= va_arg(*pParam
, uno_ExtEnvironment
*);
186 pUnoI
->acquire(pUnoI
);
187 pEnv
->registerInterface(pEnv
, reinterpret_cast<void **>(&pUnoI
), pOid
, pTypeDescr
);
191 Proxy::Proxy(uno::Mapping to_from
,
192 uno_Environment
* pTo
,
193 uno_Environment
* pFrom
,
194 uno_Interface
* pUnoI
,
195 typelib_InterfaceTypeDescription
* pTypeDescr
,
196 OUString
const & rOId
,
197 cppu::helper::purpenv::ProbeFun
* probeFun
,
203 m_from_to (pFrom
, pTo
),
204 m_to_from (std::move(to_from
)),
206 m_pTypeDescr (pTypeDescr
),
208 m_probeFun (probeFun
),
209 m_pProbeContext(pProbeContext
)
211 SAL_INFO("cppu.purpenv", "LIFE: Proxy::Proxy(<>) -> " << this);
213 typelib_typedescription_acquire(&m_pTypeDescr
->aBase
);
214 if (!m_pTypeDescr
->aBase
.bComplete
)
215 typelib_typedescription_complete(reinterpret_cast<typelib_TypeDescription
**>(&m_pTypeDescr
));
217 OSL_ENSURE(m_pTypeDescr
->aBase
.bComplete
, "### type is incomplete!");
219 uno_Environment_invoke(m_to
.get(), s_acquireAndRegister_v
, m_pUnoI
, rOId
.pData
, pTypeDescr
, m_to
.get());
222 uno_Interface::acquire
= s_Proxy_acquire
;
223 uno_Interface::release
= s_Proxy_release
;
224 uno_Interface::pDispatcher
= s_Proxy_dispatch
;
227 extern "C" { static void s_releaseAndRevoke_v(va_list * pParam
)
229 uno_ExtEnvironment
* pEnv
= va_arg(*pParam
, uno_ExtEnvironment
*);
230 uno_Interface
* pUnoI
= va_arg(*pParam
, uno_Interface
*);
232 pEnv
->revokeInterface(pEnv
, pUnoI
);
233 pUnoI
->release(pUnoI
);
238 SAL_INFO("cppu.purpenv", "LIFE: Proxy::~Proxy() -> " << this);
240 uno_Environment_invoke(m_to
.get(), s_releaseAndRevoke_v
, m_to
.get(), m_pUnoI
);
242 typelib_typedescription_release(&m_pTypeDescr
->aBase
);
245 static uno::TypeDescription
getAcquireMethod()
247 typelib_TypeDescriptionReference
* type_XInterface
=
248 * typelib_static_type_getByTypeClass(typelib_TypeClass_INTERFACE
);
250 typelib_TypeDescription
* pTXInterfaceDescr
= nullptr;
251 TYPELIB_DANGER_GET (&pTXInterfaceDescr
, type_XInterface
);
252 uno::TypeDescription
acquire(
253 reinterpret_cast< typelib_InterfaceTypeDescription
* >(
254 pTXInterfaceDescr
)->ppAllMembers
[1]);
255 TYPELIB_DANGER_RELEASE(pTXInterfaceDescr
);
260 static uno::TypeDescription
getReleaseMethod()
262 typelib_TypeDescriptionReference
* type_XInterface
=
263 * typelib_static_type_getByTypeClass(typelib_TypeClass_INTERFACE
);
265 typelib_TypeDescription
* pTXInterfaceDescr
= nullptr;
266 TYPELIB_DANGER_GET (&pTXInterfaceDescr
, type_XInterface
);
267 uno::TypeDescription
release(
268 reinterpret_cast< typelib_InterfaceTypeDescription
* >(
269 pTXInterfaceDescr
)->ppAllMembers
[2]);
270 TYPELIB_DANGER_RELEASE(pTXInterfaceDescr
);
275 static uno::TypeDescription
s_acquireMethod(getAcquireMethod());
276 static uno::TypeDescription
s_releaseMethod(getReleaseMethod());
278 void Proxy::acquire()
284 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID
),
287 s_acquireMethod
.get(),
292 if (osl_atomic_increment(&m_nRef
) == 1)
294 // rebirth of proxy zombie
296 m_from
.get()->pExtEnv
->registerProxyInterface(m_from
.get()->pExtEnv
,
301 OSL_ASSERT(pThis
== this);
308 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID
),
311 s_acquireMethod
.get(),
318 void Proxy::release()
320 cppu::helper::purpenv::ProbeFun
* probeFun
= m_probeFun
;
321 void * pProbeContext
= m_pProbeContext
;
327 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID
),
330 s_releaseMethod
.get(),
335 if (osl_atomic_decrement(&m_nRef
) == 0)
336 m_from
.get()->pExtEnv
->revokeInterface(m_from
.get()->pExtEnv
, this);
342 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID
),
345 s_releaseMethod
.get(),
354 static void s_type_destructData_v(va_list * pParam
)
356 void * ret
= va_arg(*pParam
, void *);
357 typelib_TypeDescriptionReference
* pReturnTypeRef
= va_arg(*pParam
, typelib_TypeDescriptionReference
*);
359 uno_type_destructData(ret
, pReturnTypeRef
, nullptr);
362 static void s_dispatcher_v(va_list * pParam
)
364 uno_Interface
* pUnoI
= va_arg(*pParam
, uno_Interface
*);
365 typelib_TypeDescription
const * pMemberType
= va_arg(*pParam
, typelib_TypeDescription
const *);
366 void * pReturn
= va_arg(*pParam
, void *);
367 void ** pArgs
= va_arg(*pParam
, void **);
368 uno_Any
** ppException
= va_arg(*pParam
, uno_Any
**);
370 pUnoI
->pDispatcher(pUnoI
, pMemberType
, pReturn
, pArgs
, ppException
);
374 void Proxy::dispatch(typelib_TypeDescriptionReference
* pReturnTypeRef
,
375 typelib_MethodParameter
* pParams
,
377 typelib_TypeDescription
const * pMemberType
,
380 uno_Any
** ppException
)
394 void ** args
= static_cast<void **>(alloca( sizeof (void *) * nParams
));
396 typelib_TypeDescription
* return_td
= nullptr;
397 void * ret
= pReturn
;
400 TYPELIB_DANGER_GET(&return_td
, pReturnTypeRef
);
402 if (relatesToInterface(return_td
))
403 ret
= alloca(return_td
->nSize
);
405 TYPELIB_DANGER_RELEASE(return_td
);
408 for (sal_Int32 nPos
= 0; nPos
< nParams
; ++ nPos
)
410 typelib_MethodParameter
const & param
= pParams
[nPos
];
411 typelib_TypeDescription
* td
= nullptr;
412 TYPELIB_DANGER_GET( &td
, param
.pTypeRef
);
413 if (relatesToInterface(td
))
415 args
[nPos
] = alloca(td
->nSize
);
418 uno_copyAndConvertData(args
[nPos
], pArgs
[nPos
], td
, m_from_to
.get());
423 args
[nPos
] = pArgs
[nPos
];
425 TYPELIB_DANGER_RELEASE( td
);
429 uno_Any
* exc
= &exc_data
;
431 // do the UNO call...
432 uno_Environment_invoke(m_to
.get(), s_dispatcher_v
, m_pUnoI
, pMemberType
, ret
, args
, &exc
);
436 for (sal_Int32 nPos
= 0; nPos
< nParams
; ++ nPos
)
438 if (args
[nPos
] != pArgs
[nPos
])
440 typelib_MethodParameter
const & param
= pParams
[nPos
];
443 if (param
.bIn
) // is inout
445 uno_type_destructData(pArgs
[nPos
], param
.pTypeRef
, nullptr);
447 uno_type_copyAndConvertData(pArgs
[ nPos
],
452 uno_Environment_invoke(m_to
.get(), s_type_destructData_v
, args
[nPos
], param
.pTypeRef
, 0);
457 uno_type_copyAndConvertData(pReturn
,
462 uno_Environment_invoke(m_to
.get(), s_type_destructData_v
, ret
, pReturnTypeRef
, 0);
465 *ppException
= nullptr;
467 else // exception occurred
469 for (sal_Int32 nPos
= 0; nPos
< nParams
; ++ nPos
)
471 if (args
[nPos
] != pArgs
[nPos
])
473 typelib_MethodParameter
const & param
= pParams
[nPos
];
476 uno_Environment_invoke(m_to
.get(), s_type_destructData_v
, args
[nPos
], param
.pTypeRef
, 0);
481 uno_type_any_constructAndConvert(*ppException
,
486 // FIXME: need to destruct in m_to
487 uno_any_destruct(exc
, nullptr);
503 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */