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