merge the formfield patch from ooo-build
[ooovba.git] / bridges / source / cpp_uno / shared / cppinterfaceproxy.cxx
blob76fd468f2b756320d7eb40f364ff04357ad97aca
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: cppinterfaceproxy.cxx,v $
10 * $Revision: 1.9 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
32 // MARKER(update_precomp.py): autogen include statement, do not remove
33 #include "precompiled_bridges.hxx"
35 #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx"
37 #include "guardedarray.hxx"
39 #include "bridges/cpp_uno/shared/bridge.hxx"
40 #include "bridges/cpp_uno/shared/vtablefactory.hxx"
42 #include "com/sun/star/uno/XInterface.hpp"
43 #include "osl/diagnose.h"
44 #include "osl/getglobalmutex.hxx"
45 #include "osl/interlck.h"
46 #include "osl/mutex.hxx"
47 #include "rtl/instance.hxx"
48 #include "typelib/typedescription.h"
50 #include <cstddef>
51 #include <new>
54 static bridges::cpp_uno::shared::VtableFactory * pInstance;
56 #if defined(__GNUG__) && !defined(__MINGW32__)
57 void dso_init(void) __attribute__((constructor));
58 void dso_exit(void) __attribute__((destructor));
59 #endif
61 void dso_init(void) {
62 if (!pInstance)
63 pInstance = new bridges::cpp_uno::shared::VtableFactory();
66 void dso_exit(void) {
67 if (pInstance)
69 delete pInstance;
70 pInstance = NULL;
74 #ifdef __SUNPRO_CC
75 # pragma init(dso_init)
76 # pragma fini(dso_exit)
77 #endif
81 namespace {
83 struct InitVtableFactory {
84 bridges::cpp_uno::shared::VtableFactory * operator()() {
85 return pInstance;
89 bridges::cpp_uno::shared::VtableFactory * getVtableFactory() {
90 return rtl_Instance<
91 bridges::cpp_uno::shared::VtableFactory, InitVtableFactory,
92 osl::MutexGuard, osl::GetGlobalMutex >::create(
93 InitVtableFactory(), osl::GetGlobalMutex());
98 namespace bridges { namespace cpp_uno { namespace shared {
100 void freeCppInterfaceProxy(uno_ExtEnvironment * pEnv, void * pInterface)
102 CppInterfaceProxy * pThis = CppInterfaceProxy::castInterfaceToProxy(
103 pInterface);
104 if (pEnv != pThis->pBridge->getCppEnv()) {
105 OSL_ASSERT(false);
108 (*pThis->pBridge->getUnoEnv()->revokeInterface)(
109 pThis->pBridge->getUnoEnv(), pThis->pUnoI );
110 (*pThis->pUnoI->release)( pThis->pUnoI );
111 ::typelib_typedescription_release(
112 (typelib_TypeDescription *)pThis->pTypeDescr );
113 pThis->pBridge->release();
115 #if OSL_DEBUG_LEVEL > 1
116 *(int *)pInterface = 0xdeadbabe;
117 #endif
118 pThis->~CppInterfaceProxy();
119 delete[] reinterpret_cast< char * >(pThis);
122 com::sun::star::uno::XInterface * CppInterfaceProxy::create(
123 bridges::cpp_uno::shared::Bridge * pBridge, uno_Interface * pUnoI,
124 typelib_InterfaceTypeDescription * pTypeDescr, rtl::OUString const & rOId)
125 SAL_THROW(())
127 typelib_typedescription_complete(
128 reinterpret_cast< typelib_TypeDescription ** >(&pTypeDescr));
129 bridges::cpp_uno::shared::VtableFactory::Vtables aVtables(
130 getVtableFactory()->getVtables(pTypeDescr));
131 bridges::cpp_uno::shared::GuardedArray< char > pMemory(
132 new char[
133 sizeof (CppInterfaceProxy)
134 + (aVtables.count - 1) * sizeof (void **)]);
135 new(pMemory.get()) CppInterfaceProxy(pBridge, pUnoI, pTypeDescr, rOId);
136 CppInterfaceProxy * pProxy = reinterpret_cast< CppInterfaceProxy * >(
137 pMemory.release());
138 for (sal_Int32 i = 0; i < aVtables.count; ++i) {
139 pProxy->vtables[i] = VtableFactory::mapBlockToVtable(
140 aVtables.blocks[i].start);
142 return castProxyToInterface(pProxy);
145 void CppInterfaceProxy::acquireProxy() SAL_THROW(())
147 if (1 == osl_incrementInterlockedCount( &nRef ))
149 // rebirth of proxy zombie
150 // register at cpp env
151 void * pThis = castProxyToInterface( this );
152 (*pBridge->getCppEnv()->registerProxyInterface)(
153 pBridge->getCppEnv(), &pThis, freeCppInterfaceProxy, oid.pData,
154 pTypeDescr );
155 OSL_ASSERT( pThis == castProxyToInterface( this ) );
159 void CppInterfaceProxy::releaseProxy() SAL_THROW(())
161 if (! osl_decrementInterlockedCount( &nRef )) // last release
163 // revoke from cpp env
164 (*pBridge->getCppEnv()->revokeInterface)(
165 pBridge->getCppEnv(), castProxyToInterface( this ) );
169 CppInterfaceProxy::CppInterfaceProxy(
170 bridges::cpp_uno::shared::Bridge * pBridge_, uno_Interface * pUnoI_,
171 typelib_InterfaceTypeDescription * pTypeDescr_, rtl::OUString const & rOId_)
172 SAL_THROW(())
173 : nRef( 1 )
174 , pBridge( pBridge_ )
175 , pUnoI( pUnoI_ )
176 , pTypeDescr( pTypeDescr_ )
177 , oid( rOId_ )
179 pBridge->acquire();
180 ::typelib_typedescription_acquire( (typelib_TypeDescription *)pTypeDescr );
181 (*pUnoI->acquire)( pUnoI );
182 (*pBridge->getUnoEnv()->registerInterface)(
183 pBridge->getUnoEnv(), reinterpret_cast< void ** >( &pUnoI ), oid.pData,
184 pTypeDescr );
187 CppInterfaceProxy::~CppInterfaceProxy()
190 com::sun::star::uno::XInterface * CppInterfaceProxy::castProxyToInterface(
191 CppInterfaceProxy * pProxy)
193 return reinterpret_cast< com::sun::star::uno::XInterface * >(
194 &pProxy->vtables);
197 CppInterfaceProxy * CppInterfaceProxy::castInterfaceToProxy(void * pInterface)
199 // pInterface == &pProxy->vtables (this emulated offsetof is not truly
200 // portable):
201 char const * const base = reinterpret_cast< char const * >(16);
202 std::ptrdiff_t const offset = reinterpret_cast< char const * >(
203 &reinterpret_cast< CppInterfaceProxy const * >(base)->vtables) - base;
204 return reinterpret_cast< CppInterfaceProxy * >(
205 static_cast< char * >(pInterface) - offset);
208 } } }