1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
31 #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx"
33 #include "guardedarray.hxx"
35 #include "bridges/cpp_uno/shared/bridge.hxx"
36 #include "bridges/cpp_uno/shared/vtablefactory.hxx"
38 #include "com/sun/star/uno/XInterface.hpp"
39 #include "osl/diagnose.h"
40 #include "osl/getglobalmutex.hxx"
41 #include "osl/interlck.h"
42 #include "osl/mutex.hxx"
43 #include "rtl/instance.hxx"
44 #include "typelib/typedescription.h"
50 static bridges::cpp_uno::shared::VtableFactory
* pInstance
;
52 #if defined(__GNUG__) && !defined(__MINGW32__)
53 void dso_init(void) __attribute__((constructor
));
54 void dso_exit(void) __attribute__((destructor
));
59 pInstance
= new bridges::cpp_uno::shared::VtableFactory();
71 # pragma init(dso_init)
72 # pragma fini(dso_exit)
79 struct InitVtableFactory
{
80 bridges::cpp_uno::shared::VtableFactory
* operator()() {
85 bridges::cpp_uno::shared::VtableFactory
* getVtableFactory() {
87 bridges::cpp_uno::shared::VtableFactory
, InitVtableFactory
,
88 osl::MutexGuard
, osl::GetGlobalMutex
>::create(
89 InitVtableFactory(), osl::GetGlobalMutex());
94 namespace bridges
{ namespace cpp_uno
{ namespace shared
{
96 void freeCppInterfaceProxy(uno_ExtEnvironment
* pEnv
, void * pInterface
)
98 CppInterfaceProxy
* pThis
= CppInterfaceProxy::castInterfaceToProxy(
100 if (pEnv
!= pThis
->pBridge
->getCppEnv()) {
104 (*pThis
->pBridge
->getUnoEnv()->revokeInterface
)(
105 pThis
->pBridge
->getUnoEnv(), pThis
->pUnoI
);
106 (*pThis
->pUnoI
->release
)( pThis
->pUnoI
);
107 ::typelib_typedescription_release(
108 (typelib_TypeDescription
*)pThis
->pTypeDescr
);
109 pThis
->pBridge
->release();
111 #if OSL_DEBUG_LEVEL > 1
112 *(int *)pInterface
= 0xdeadbabe;
114 pThis
->~CppInterfaceProxy();
115 delete[] reinterpret_cast< char * >(pThis
);
118 com::sun::star::uno::XInterface
* CppInterfaceProxy::create(
119 bridges::cpp_uno::shared::Bridge
* pBridge
, uno_Interface
* pUnoI
,
120 typelib_InterfaceTypeDescription
* pTypeDescr
, rtl::OUString
const & rOId
)
123 typelib_typedescription_complete(
124 reinterpret_cast< typelib_TypeDescription
** >(&pTypeDescr
));
125 bridges::cpp_uno::shared::VtableFactory::Vtables
aVtables(
126 getVtableFactory()->getVtables(pTypeDescr
));
127 bridges::cpp_uno::shared::GuardedArray
< char > pMemory(
129 sizeof (CppInterfaceProxy
)
130 + (aVtables
.count
- 1) * sizeof (void **)]);
131 new(pMemory
.get()) CppInterfaceProxy(pBridge
, pUnoI
, pTypeDescr
, rOId
);
132 CppInterfaceProxy
* pProxy
= reinterpret_cast< CppInterfaceProxy
* >(
134 for (sal_Int32 i
= 0; i
< aVtables
.count
; ++i
) {
135 pProxy
->vtables
[i
] = VtableFactory::mapBlockToVtable(
136 aVtables
.blocks
[i
].start
);
138 return castProxyToInterface(pProxy
);
141 void CppInterfaceProxy::acquireProxy() SAL_THROW(())
143 if (1 == osl_incrementInterlockedCount( &nRef
))
145 // rebirth of proxy zombie
146 // register at cpp env
147 void * pThis
= castProxyToInterface( this );
148 (*pBridge
->getCppEnv()->registerProxyInterface
)(
149 pBridge
->getCppEnv(), &pThis
, freeCppInterfaceProxy
, oid
.pData
,
151 OSL_ASSERT( pThis
== castProxyToInterface( this ) );
155 void CppInterfaceProxy::releaseProxy() SAL_THROW(())
157 if (! osl_decrementInterlockedCount( &nRef
)) // last release
159 // revoke from cpp env
160 (*pBridge
->getCppEnv()->revokeInterface
)(
161 pBridge
->getCppEnv(), castProxyToInterface( this ) );
165 CppInterfaceProxy::CppInterfaceProxy(
166 bridges::cpp_uno::shared::Bridge
* pBridge_
, uno_Interface
* pUnoI_
,
167 typelib_InterfaceTypeDescription
* pTypeDescr_
, rtl::OUString
const & rOId_
)
170 , pBridge( pBridge_
)
172 , pTypeDescr( pTypeDescr_
)
176 ::typelib_typedescription_acquire( (typelib_TypeDescription
*)pTypeDescr
);
177 (*pUnoI
->acquire
)( pUnoI
);
178 (*pBridge
->getUnoEnv()->registerInterface
)(
179 pBridge
->getUnoEnv(), reinterpret_cast< void ** >( &pUnoI
), oid
.pData
,
183 CppInterfaceProxy::~CppInterfaceProxy()
186 com::sun::star::uno::XInterface
* CppInterfaceProxy::castProxyToInterface(
187 CppInterfaceProxy
* pProxy
)
189 return reinterpret_cast< com::sun::star::uno::XInterface
* >(
193 CppInterfaceProxy
* CppInterfaceProxy::castInterfaceToProxy(void * pInterface
)
195 // pInterface == &pProxy->vtables (this emulated offsetof is not truly
197 char const * const base
= reinterpret_cast< char const * >(16);
198 std::ptrdiff_t const offset
= reinterpret_cast< char const * >(
199 &reinterpret_cast< CppInterfaceProxy
const * >(base
)->vtables
) - base
;
200 return reinterpret_cast< CppInterfaceProxy
* >(
201 static_cast< char * >(pInterface
) - offset
);
206 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */