1*61dff127SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*61dff127SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*61dff127SAndrew Rist * or more contributor license agreements. See the NOTICE file 5*61dff127SAndrew Rist * distributed with this work for additional information 6*61dff127SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*61dff127SAndrew Rist * to you under the Apache License, Version 2.0 (the 8*61dff127SAndrew Rist * "License"); you may not use this file except in compliance 9*61dff127SAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 11*61dff127SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 13*61dff127SAndrew Rist * Unless required by applicable law or agreed to in writing, 14*61dff127SAndrew Rist * software distributed under the License is distributed on an 15*61dff127SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*61dff127SAndrew Rist * KIND, either express or implied. See the License for the 17*61dff127SAndrew Rist * specific language governing permissions and limitations 18*61dff127SAndrew Rist * under the License. 19cdf0e10cSrcweir * 20*61dff127SAndrew Rist *************************************************************/ 21*61dff127SAndrew Rist 22*61dff127SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir 25cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 26cdf0e10cSrcweir #include "precompiled_bridges.hxx" 27cdf0e10cSrcweir 28cdf0e10cSrcweir #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" 29cdf0e10cSrcweir 30cdf0e10cSrcweir #include "guardedarray.hxx" 31cdf0e10cSrcweir 32cdf0e10cSrcweir #include "bridges/cpp_uno/shared/bridge.hxx" 33cdf0e10cSrcweir #include "bridges/cpp_uno/shared/vtablefactory.hxx" 34cdf0e10cSrcweir 35cdf0e10cSrcweir #include "com/sun/star/uno/XInterface.hpp" 36cdf0e10cSrcweir #include "osl/diagnose.h" 37cdf0e10cSrcweir #include "osl/getglobalmutex.hxx" 38cdf0e10cSrcweir #include "osl/interlck.h" 39cdf0e10cSrcweir #include "osl/mutex.hxx" 40cdf0e10cSrcweir #include "rtl/instance.hxx" 41cdf0e10cSrcweir #include "typelib/typedescription.h" 42cdf0e10cSrcweir 43cdf0e10cSrcweir #include <cstddef> 44cdf0e10cSrcweir #include <new> 45cdf0e10cSrcweir 46cdf0e10cSrcweir 47cdf0e10cSrcweir static bridges::cpp_uno::shared::VtableFactory * pInstance; 48cdf0e10cSrcweir 49cdf0e10cSrcweir #if defined(__GNUG__) && !defined(__MINGW32__) 50cdf0e10cSrcweir void dso_init(void) __attribute__((constructor)); 51cdf0e10cSrcweir void dso_exit(void) __attribute__((destructor)); 52cdf0e10cSrcweir #endif 53cdf0e10cSrcweir 54cdf0e10cSrcweir void dso_init(void) { 55cdf0e10cSrcweir if (!pInstance) 56cdf0e10cSrcweir pInstance = new bridges::cpp_uno::shared::VtableFactory(); 57cdf0e10cSrcweir } 58cdf0e10cSrcweir 59cdf0e10cSrcweir void dso_exit(void) { 60cdf0e10cSrcweir if (pInstance) 61cdf0e10cSrcweir { 62cdf0e10cSrcweir delete pInstance; 63cdf0e10cSrcweir pInstance = NULL; 64cdf0e10cSrcweir } 65cdf0e10cSrcweir } 66cdf0e10cSrcweir 67cdf0e10cSrcweir #ifdef __SUNPRO_CC 68cdf0e10cSrcweir # pragma init(dso_init) 69cdf0e10cSrcweir # pragma fini(dso_exit) 70cdf0e10cSrcweir #endif 71cdf0e10cSrcweir 72cdf0e10cSrcweir 73cdf0e10cSrcweir 74cdf0e10cSrcweir namespace { 75cdf0e10cSrcweir 76cdf0e10cSrcweir struct InitVtableFactory { 77cdf0e10cSrcweir bridges::cpp_uno::shared::VtableFactory * operator()() { 78cdf0e10cSrcweir return pInstance; 79cdf0e10cSrcweir } 80cdf0e10cSrcweir }; 81cdf0e10cSrcweir 82cdf0e10cSrcweir bridges::cpp_uno::shared::VtableFactory * getVtableFactory() { 83cdf0e10cSrcweir return rtl_Instance< 84cdf0e10cSrcweir bridges::cpp_uno::shared::VtableFactory, InitVtableFactory, 85cdf0e10cSrcweir osl::MutexGuard, osl::GetGlobalMutex >::create( 86cdf0e10cSrcweir InitVtableFactory(), osl::GetGlobalMutex()); 87cdf0e10cSrcweir } 88cdf0e10cSrcweir 89cdf0e10cSrcweir } 90cdf0e10cSrcweir 91cdf0e10cSrcweir namespace bridges { namespace cpp_uno { namespace shared { 92cdf0e10cSrcweir 93cdf0e10cSrcweir void freeCppInterfaceProxy(uno_ExtEnvironment * pEnv, void * pInterface) 94cdf0e10cSrcweir { 95cdf0e10cSrcweir CppInterfaceProxy * pThis = CppInterfaceProxy::castInterfaceToProxy( 96cdf0e10cSrcweir pInterface); 97cdf0e10cSrcweir if (pEnv != pThis->pBridge->getCppEnv()) { 98cdf0e10cSrcweir OSL_ASSERT(false); 99cdf0e10cSrcweir } 100cdf0e10cSrcweir 101cdf0e10cSrcweir (*pThis->pBridge->getUnoEnv()->revokeInterface)( 102cdf0e10cSrcweir pThis->pBridge->getUnoEnv(), pThis->pUnoI ); 103cdf0e10cSrcweir (*pThis->pUnoI->release)( pThis->pUnoI ); 104cdf0e10cSrcweir ::typelib_typedescription_release( 105cdf0e10cSrcweir (typelib_TypeDescription *)pThis->pTypeDescr ); 106cdf0e10cSrcweir pThis->pBridge->release(); 107cdf0e10cSrcweir 108cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 109cdf0e10cSrcweir *(int *)pInterface = 0xdeadbabe; 110cdf0e10cSrcweir #endif 111cdf0e10cSrcweir pThis->~CppInterfaceProxy(); 112cdf0e10cSrcweir delete[] reinterpret_cast< char * >(pThis); 113cdf0e10cSrcweir } 114cdf0e10cSrcweir 115cdf0e10cSrcweir com::sun::star::uno::XInterface * CppInterfaceProxy::create( 116cdf0e10cSrcweir bridges::cpp_uno::shared::Bridge * pBridge, uno_Interface * pUnoI, 117cdf0e10cSrcweir typelib_InterfaceTypeDescription * pTypeDescr, rtl::OUString const & rOId) 118cdf0e10cSrcweir SAL_THROW(()) 119cdf0e10cSrcweir { 120cdf0e10cSrcweir typelib_typedescription_complete( 121cdf0e10cSrcweir reinterpret_cast< typelib_TypeDescription ** >(&pTypeDescr)); 122cdf0e10cSrcweir bridges::cpp_uno::shared::VtableFactory::Vtables aVtables( 123cdf0e10cSrcweir getVtableFactory()->getVtables(pTypeDescr)); 124cdf0e10cSrcweir bridges::cpp_uno::shared::GuardedArray< char > pMemory( 125cdf0e10cSrcweir new char[ 126cdf0e10cSrcweir sizeof (CppInterfaceProxy) 127cdf0e10cSrcweir + (aVtables.count - 1) * sizeof (void **)]); 128cdf0e10cSrcweir new(pMemory.get()) CppInterfaceProxy(pBridge, pUnoI, pTypeDescr, rOId); 129cdf0e10cSrcweir CppInterfaceProxy * pProxy = reinterpret_cast< CppInterfaceProxy * >( 130cdf0e10cSrcweir pMemory.release()); 131cdf0e10cSrcweir for (sal_Int32 i = 0; i < aVtables.count; ++i) { 132cdf0e10cSrcweir pProxy->vtables[i] = VtableFactory::mapBlockToVtable( 133cdf0e10cSrcweir aVtables.blocks[i].start); 134cdf0e10cSrcweir } 135cdf0e10cSrcweir return castProxyToInterface(pProxy); 136cdf0e10cSrcweir } 137cdf0e10cSrcweir 138cdf0e10cSrcweir void CppInterfaceProxy::acquireProxy() SAL_THROW(()) 139cdf0e10cSrcweir { 140cdf0e10cSrcweir if (1 == osl_incrementInterlockedCount( &nRef )) 141cdf0e10cSrcweir { 142cdf0e10cSrcweir // rebirth of proxy zombie 143cdf0e10cSrcweir // register at cpp env 144cdf0e10cSrcweir void * pThis = castProxyToInterface( this ); 145cdf0e10cSrcweir (*pBridge->getCppEnv()->registerProxyInterface)( 146cdf0e10cSrcweir pBridge->getCppEnv(), &pThis, freeCppInterfaceProxy, oid.pData, 147cdf0e10cSrcweir pTypeDescr ); 148cdf0e10cSrcweir OSL_ASSERT( pThis == castProxyToInterface( this ) ); 149cdf0e10cSrcweir } 150cdf0e10cSrcweir } 151cdf0e10cSrcweir 152cdf0e10cSrcweir void CppInterfaceProxy::releaseProxy() SAL_THROW(()) 153cdf0e10cSrcweir { 154cdf0e10cSrcweir if (! osl_decrementInterlockedCount( &nRef )) // last release 155cdf0e10cSrcweir { 156cdf0e10cSrcweir // revoke from cpp env 157cdf0e10cSrcweir (*pBridge->getCppEnv()->revokeInterface)( 158cdf0e10cSrcweir pBridge->getCppEnv(), castProxyToInterface( this ) ); 159cdf0e10cSrcweir } 160cdf0e10cSrcweir } 161cdf0e10cSrcweir 162cdf0e10cSrcweir CppInterfaceProxy::CppInterfaceProxy( 163cdf0e10cSrcweir bridges::cpp_uno::shared::Bridge * pBridge_, uno_Interface * pUnoI_, 164cdf0e10cSrcweir typelib_InterfaceTypeDescription * pTypeDescr_, rtl::OUString const & rOId_) 165cdf0e10cSrcweir SAL_THROW(()) 166cdf0e10cSrcweir : nRef( 1 ) 167cdf0e10cSrcweir , pBridge( pBridge_ ) 168cdf0e10cSrcweir , pUnoI( pUnoI_ ) 169cdf0e10cSrcweir , pTypeDescr( pTypeDescr_ ) 170cdf0e10cSrcweir , oid( rOId_ ) 171cdf0e10cSrcweir { 172cdf0e10cSrcweir pBridge->acquire(); 173cdf0e10cSrcweir ::typelib_typedescription_acquire( (typelib_TypeDescription *)pTypeDescr ); 174cdf0e10cSrcweir (*pUnoI->acquire)( pUnoI ); 175cdf0e10cSrcweir (*pBridge->getUnoEnv()->registerInterface)( 176cdf0e10cSrcweir pBridge->getUnoEnv(), reinterpret_cast< void ** >( &pUnoI ), oid.pData, 177cdf0e10cSrcweir pTypeDescr ); 178cdf0e10cSrcweir } 179cdf0e10cSrcweir 180cdf0e10cSrcweir CppInterfaceProxy::~CppInterfaceProxy() 181cdf0e10cSrcweir {} 182cdf0e10cSrcweir 183cdf0e10cSrcweir com::sun::star::uno::XInterface * CppInterfaceProxy::castProxyToInterface( 184cdf0e10cSrcweir CppInterfaceProxy * pProxy) 185cdf0e10cSrcweir { 186cdf0e10cSrcweir return reinterpret_cast< com::sun::star::uno::XInterface * >( 187cdf0e10cSrcweir &pProxy->vtables); 188cdf0e10cSrcweir } 189cdf0e10cSrcweir 190cdf0e10cSrcweir CppInterfaceProxy * CppInterfaceProxy::castInterfaceToProxy(void * pInterface) 191cdf0e10cSrcweir { 192cdf0e10cSrcweir // pInterface == &pProxy->vtables (this emulated offsetof is not truly 193cdf0e10cSrcweir // portable): 194cdf0e10cSrcweir char const * const base = reinterpret_cast< char const * >(16); 195cdf0e10cSrcweir std::ptrdiff_t const offset = reinterpret_cast< char const * >( 196cdf0e10cSrcweir &reinterpret_cast< CppInterfaceProxy const * >(base)->vtables) - base; 197cdf0e10cSrcweir return reinterpret_cast< CppInterfaceProxy * >( 198cdf0e10cSrcweir static_cast< char * >(pInterface) - offset); 199cdf0e10cSrcweir } 200cdf0e10cSrcweir 201cdf0e10cSrcweir } } } 202