| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_bridges.hxx" |
| |
| #include "bridges/cpp_uno/shared/bridge.hxx" |
| |
| #include "component.hxx" |
| |
| #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" |
| #include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" |
| |
| #include "com/sun/star/uno/XInterface.hpp" |
| #include "osl/diagnose.h" |
| #include "osl/interlck.h" |
| #include "rtl/ustring.h" |
| #include "sal/types.h" |
| #include "typelib/typedescription.h" |
| #include "uno/dispatcher.h" |
| #include "uno/environment.h" |
| #include "uno/mapping.h" |
| |
| namespace bridges { namespace cpp_uno { namespace shared { |
| |
| void freeMapping(uno_Mapping * pMapping) |
| { |
| delete static_cast< Bridge::Mapping * >( pMapping )->pBridge; |
| } |
| |
| void acquireMapping(uno_Mapping * pMapping) |
| { |
| static_cast< Bridge::Mapping * >( pMapping )->pBridge->acquire(); |
| } |
| |
| void releaseMapping(uno_Mapping * pMapping) |
| { |
| static_cast< Bridge::Mapping * >( pMapping )->pBridge->release(); |
| } |
| |
| void cpp2unoMapping( |
| uno_Mapping * pMapping, void ** ppUnoI, void * pCppI, |
| typelib_InterfaceTypeDescription * pTypeDescr) |
| { |
| OSL_ENSURE( ppUnoI && pTypeDescr, "### null ptr!" ); |
| if (*ppUnoI) |
| { |
| (*reinterpret_cast< uno_Interface * >( *ppUnoI )->release)( |
| reinterpret_cast< uno_Interface * >( *ppUnoI ) ); |
| *ppUnoI = 0; |
| } |
| if (pCppI) |
| { |
| Bridge * pBridge = static_cast< Bridge::Mapping * >( pMapping )->pBridge; |
| |
| // get object id of interface to be wrapped |
| rtl_uString * pOId = 0; |
| (*pBridge->pCppEnv->getObjectIdentifier)( |
| pBridge->pCppEnv, &pOId, pCppI ); |
| OSL_ASSERT( pOId ); |
| |
| // try to get any known interface from target environment |
| (*pBridge->pUnoEnv->getRegisteredInterface)( |
| pBridge->pUnoEnv, ppUnoI, pOId, pTypeDescr ); |
| |
| if (! *ppUnoI) // no existing interface, register new proxy interface |
| { |
| // try to publish a new proxy (refcount initially 1) |
| uno_Interface * pSurrogate |
| = bridges::cpp_uno::shared::UnoInterfaceProxy::create( |
| pBridge, |
| static_cast< ::com::sun::star::uno::XInterface * >( pCppI ), |
| pTypeDescr, pOId ); |
| |
| // proxy may be exchanged during registration |
| (*pBridge->pUnoEnv->registerProxyInterface)( |
| pBridge->pUnoEnv, reinterpret_cast< void ** >( &pSurrogate ), |
| freeUnoInterfaceProxy, pOId, |
| pTypeDescr ); |
| |
| *ppUnoI = pSurrogate; |
| } |
| ::rtl_uString_release( pOId ); |
| } |
| } |
| |
| void uno2cppMapping( |
| uno_Mapping * pMapping, void ** ppCppI, void * pUnoI, |
| typelib_InterfaceTypeDescription * pTypeDescr) |
| { |
| OSL_ASSERT( ppCppI && pTypeDescr ); |
| if (*ppCppI) |
| { |
| static_cast< ::com::sun::star::uno::XInterface * >( *ppCppI )-> |
| release(); |
| *ppCppI = 0; |
| } |
| if (pUnoI) |
| { |
| Bridge * pBridge = static_cast< Bridge::Mapping * >( pMapping )->pBridge; |
| |
| // get object id of uno interface to be wrapped |
| rtl_uString * pOId = 0; |
| (*pBridge->pUnoEnv->getObjectIdentifier)( |
| pBridge->pUnoEnv, &pOId, pUnoI ); |
| OSL_ASSERT( pOId ); |
| |
| // try to get any known interface from target environment |
| (*pBridge->pCppEnv->getRegisteredInterface)( |
| pBridge->pCppEnv, ppCppI, pOId, pTypeDescr ); |
| |
| if (! *ppCppI) // no existing interface, register new proxy interface |
| { |
| // try to publish a new proxy (ref count initially 1) |
| com::sun::star::uno::XInterface * pProxy |
| = bridges::cpp_uno::shared::CppInterfaceProxy::create( |
| pBridge, static_cast< uno_Interface * >( pUnoI ), |
| pTypeDescr, pOId ); |
| |
| // proxy may be exchanged during registration |
| (*pBridge->pCppEnv->registerProxyInterface)( |
| pBridge->pCppEnv, reinterpret_cast< void ** >( &pProxy ), |
| freeCppInterfaceProxy, pOId, |
| pTypeDescr ); |
| |
| *ppCppI = pProxy; |
| } |
| ::rtl_uString_release( pOId ); |
| } |
| } |
| |
| uno_Mapping * Bridge::createMapping( |
| uno_ExtEnvironment * pCppEnv, uno_ExtEnvironment * pUnoEnv, |
| bool bExportCpp2Uno) SAL_THROW(()) |
| { |
| Bridge * bridge = new Bridge(pCppEnv, pUnoEnv, bExportCpp2Uno); |
| return bExportCpp2Uno ? &bridge->aCpp2Uno : &bridge->aUno2Cpp; |
| } |
| |
| void Bridge::acquire() SAL_THROW(()) |
| { |
| if (1 == osl_incrementInterlockedCount( &nRef )) |
| { |
| if (bExportCpp2Uno) |
| { |
| uno_Mapping * pMapping = &aCpp2Uno; |
| ::uno_registerMapping( |
| &pMapping, freeMapping, (uno_Environment *)pCppEnv, |
| (uno_Environment *)pUnoEnv, 0 ); |
| } |
| else |
| { |
| uno_Mapping * pMapping = &aUno2Cpp; |
| ::uno_registerMapping( |
| &pMapping, freeMapping, (uno_Environment *)pUnoEnv, |
| (uno_Environment *)pCppEnv, 0 ); |
| } |
| } |
| } |
| |
| void Bridge::release() SAL_THROW(()) |
| { |
| if (! osl_decrementInterlockedCount( &nRef )) |
| { |
| ::uno_revokeMapping( bExportCpp2Uno ? &aCpp2Uno : &aUno2Cpp ); |
| } |
| } |
| |
| Bridge::Bridge( |
| uno_ExtEnvironment * pCppEnv_, uno_ExtEnvironment * pUnoEnv_, |
| bool bExportCpp2Uno_) SAL_THROW(()) |
| : nRef( 1 ) |
| , pCppEnv( pCppEnv_ ) |
| , pUnoEnv( pUnoEnv_ ) |
| , bExportCpp2Uno( bExportCpp2Uno_ ) |
| { |
| bridges::cpp_uno::shared::g_moduleCount.modCnt.acquire( |
| &bridges::cpp_uno::shared::g_moduleCount.modCnt ); |
| |
| aCpp2Uno.pBridge = this; |
| aCpp2Uno.acquire = acquireMapping; |
| aCpp2Uno.release = releaseMapping; |
| aCpp2Uno.mapInterface = cpp2unoMapping; |
| |
| aUno2Cpp.pBridge = this; |
| aUno2Cpp.acquire = acquireMapping; |
| aUno2Cpp.release = releaseMapping; |
| aUno2Cpp.mapInterface = uno2cppMapping; |
| |
| (*((uno_Environment *)pCppEnv)->acquire)( (uno_Environment *)pCppEnv ); |
| (*((uno_Environment *)pUnoEnv)->acquire)( (uno_Environment *)pUnoEnv ); |
| } |
| |
| Bridge::~Bridge() SAL_THROW(()) |
| { |
| (*((uno_Environment *)pUnoEnv)->release)( (uno_Environment *)pUnoEnv ); |
| (*((uno_Environment *)pCppEnv)->release)( (uno_Environment *)pCppEnv ); |
| bridges::cpp_uno::shared::g_moduleCount.modCnt.release( |
| &bridges::cpp_uno::shared::g_moduleCount.modCnt ); |
| } |
| |
| } } } |