Version 3.6.0.4, tag libreoffice-3.6.0.4
[LibreOffice.git] / cli_ure / source / uno_bridge / cli_bridge.cxx
blob4463a0f39bf10847e62c175267da6d6842de8c4f
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 ************************************************************************/
29 #include <vcclr.h>
30 //ToDo: remove when build with .NET 2
31 #pragma warning(push, 1)
32 #include <windows.h>
33 #include "uno/environment.hxx"
34 #pragma warning(pop)
35 #include "rtl/unload.h"
36 #include "uno/lbnames.h"
37 #include "uno/mapping.hxx"
38 #include "typelib/typedescription.hxx"
39 #include "rtl/ustring.hxx"
41 #include "cli_bridge.h"
42 #include "cli_proxy.h"
43 #using <mscorlib.dll>
44 #if defined(_MSC_VER) && (_MSC_VER < 1400)
45 #include <_vcclrit.h>
46 #endif
48 namespace sri= System::Runtime::InteropServices;
49 using ::rtl::OUString;
50 using ::rtl::OString;
51 using ::rtl::OUStringToOString;
53 namespace cli_uno
56 extern "C"
58 void SAL_CALL Mapping_acquire( uno_Mapping * mapping )
59 SAL_THROW_EXTERN_C()
61 Mapping const * that = static_cast< Mapping const * >( mapping );
62 that->m_bridge->acquire();
64 //--------------------------------------------------------------------------------------------------
65 void SAL_CALL Mapping_release( uno_Mapping * mapping )
66 SAL_THROW_EXTERN_C()
68 Mapping const * that = static_cast< Mapping const * >( mapping );
69 that->m_bridge->release();
73 //--------------------------------------------------------------------------------------------------
74 void SAL_CALL Mapping_cli2uno(
75 uno_Mapping * mapping, void ** ppOut,
76 void * pIn, typelib_InterfaceTypeDescription * td )
77 SAL_THROW_EXTERN_C()
79 uno_Interface ** ppUnoI = (uno_Interface **)ppOut;
80 intptr_t cliI = (intptr_t)pIn;
82 OSL_ENSURE( ppUnoI && td, "### null ptr!" );
84 if (0 != *ppUnoI)
86 uno_Interface * pUnoI = *(uno_Interface **)ppUnoI;
87 (*pUnoI->release)( pUnoI );
88 *ppUnoI = 0;
90 try
92 Mapping const * that = static_cast< Mapping const * >( mapping );
93 Bridge * bridge = that->m_bridge;
95 if (0 != cliI)
97 System::Object* cliObj= sri::GCHandle::op_Explicit(cliI).Target;
98 (*ppOut)= bridge->map_cli2uno(cliObj, (typelib_TypeDescription*) td);
101 catch (BridgeRuntimeError & err)
103 #if OSL_DEBUG_LEVEL >= 1
104 OString cstr_msg(
105 OUStringToOString(
106 OUSTR("[cli_uno bridge error] ") + err.m_message, RTL_TEXTENCODING_ASCII_US ) );
107 OSL_FAIL( cstr_msg.getStr() );
108 #else
109 (void) err; // unused
110 #endif
113 //--------------------------------------------------------------------------------------------------
114 void SAL_CALL Mapping_uno2cli(
115 uno_Mapping * mapping, void ** ppOut,
116 void * pIn, typelib_InterfaceTypeDescription * td )
117 SAL_THROW_EXTERN_C()
121 OSL_ENSURE( td && ppOut, "### null ptr!" );
122 OSL_ENSURE( (sizeof(System::Char) == sizeof(sal_Unicode))
123 && (sizeof(System::Boolean) == sizeof(sal_Bool))
124 && (sizeof(System::SByte) == sizeof(sal_Int8))
125 && (sizeof(System::Int16) == sizeof(sal_Int16))
126 && (sizeof(System::UInt16) == sizeof(sal_uInt16))
127 && (sizeof(System::Int32) == sizeof(sal_Int32))
128 && (sizeof(System::UInt32) == sizeof(sal_uInt32))
129 && (sizeof(System::Int64) == sizeof(sal_Int64))
130 && (sizeof(System::UInt64) == sizeof(sal_uInt64))
131 && (sizeof(System::Single) == sizeof(float))
132 && (sizeof(System::Double) == sizeof(double)),
133 "[cli_uno bridge] incompatible .NET data types");
134 intptr_t * ppDNetI = (intptr_t *)ppOut;
135 uno_Interface * pUnoI = (uno_Interface *)pIn;
137 Mapping const * that = static_cast< Mapping const * >( mapping );
138 Bridge * bridge = that->m_bridge;
140 if (0 != *ppDNetI)
142 sri::GCHandle::op_Explicit(ppDNetI).Free();
145 if (0 != pUnoI)
147 System::Object* cliI= bridge->map_uno2cli(pUnoI, td);
148 intptr_t ptr= NULL;
149 if(cliI)
151 ptr= sri::GCHandle::op_Explicit(sri::GCHandle::Alloc(cliI))
152 #ifdef _WIN32
153 .ToInt32();
154 #else /* defined(_WIN64) */ .ToInt64();
155 #endif
157 (*ppOut)= reinterpret_cast<void*>(ptr);
160 catch (BridgeRuntimeError & err)
162 #if OSL_DEBUG_LEVEL >= 1
163 rtl::OString cstr_msg(
164 rtl::OUStringToOString(
165 OUSTR("[cli_uno bridge error] ") + err.m_message, RTL_TEXTENCODING_ASCII_US ) );
166 OSL_FAIL( cstr_msg.getStr() );
167 #else
168 (void) err; // unused
169 #endif
173 //__________________________________________________________________________________________________
174 void SAL_CALL Bridge_free( uno_Mapping * mapping )
175 SAL_THROW_EXTERN_C()
177 Mapping * that = static_cast< Mapping * >( mapping );
178 delete that->m_bridge;
181 } //extern C
182 } //namespace
184 namespace cli_uno
187 //__________________________________________________________________________________________________
188 /** ToDo
189 I doubt that the the case that the ref count raises from 0 to 1
190 can occur. uno_ext_getMapping returns an acquired mapping. Every time
191 that function is called then a new mapping is created. Following the
192 rules of ref counted objects, then if the ref count is null noone has
193 a reference to the object anymore. Hence noone can call acquire. If someone
194 calls acquire then they must have kept an unacquired pointer which is
195 illegal.
197 void Bridge::acquire() const SAL_THROW(())
199 if (1 == osl_incrementInterlockedCount( &m_ref ))
201 if (m_registered_cli2uno)
203 uno_Mapping * mapping = const_cast<Mapping*>(&m_cli2uno);
204 uno_registerMapping(
205 & const_cast<uno_Mapping*>(mapping), Bridge_free, m_uno_cli_env, (uno_Environment *)m_uno_env, 0 );
207 else
209 uno_Mapping * mapping = const_cast<Mapping*>(&m_uno2cli);
210 uno_registerMapping(
211 &mapping, Bridge_free, (uno_Environment *)m_uno_env, m_uno_cli_env, 0 );
215 //__________________________________________________________________________________________________
216 void Bridge::release() const SAL_THROW(())
218 if (! osl_decrementInterlockedCount( &m_ref ))
220 uno_revokeMapping(
221 m_registered_cli2uno
222 ? const_cast<Mapping*>(&m_cli2uno)
223 : const_cast<Mapping*>(&m_uno2cli) );
226 //__________________________________________________________________________________________________
227 Bridge::Bridge(
228 uno_Environment * uno_cli_env, uno_ExtEnvironment * uno_env,
229 bool registered_cli2uno )
230 : m_ref( 1 ),
231 m_uno_env( uno_env ),
232 m_uno_cli_env( uno_cli_env ),
233 m_registered_cli2uno( registered_cli2uno )
235 OSL_ASSERT( 0 != m_uno_cli_env && 0 != m_uno_env );
236 (*((uno_Environment *)m_uno_env)->acquire)( (uno_Environment *)m_uno_env );
237 (*m_uno_cli_env->acquire)( m_uno_cli_env );
239 // cli2uno
240 m_cli2uno.acquire = Mapping_acquire;
241 m_cli2uno.release = Mapping_release;
242 m_cli2uno.mapInterface = Mapping_cli2uno;
243 m_cli2uno.m_bridge = this;
244 // uno2cli
245 m_uno2cli.acquire = Mapping_acquire;
246 m_uno2cli.release = Mapping_release;
247 m_uno2cli.mapInterface = Mapping_uno2cli;
248 m_uno2cli.m_bridge = this;
252 //__________________________________________________________________________________________________
253 Bridge::~Bridge() SAL_THROW(())
255 //System::GC::Collect();
256 (*m_uno_cli_env->release)( m_uno_cli_env );
257 (*((uno_Environment *)m_uno_env)->release)( (uno_Environment *)m_uno_env );
262 } //namespace cli_uno
264 extern "C"
267 namespace cli_uno
269 //--------------------------------------------------------------------------------------------------
270 void SAL_CALL cli_env_disposing( uno_Environment * uno_cli_env )
271 SAL_THROW_EXTERN_C()
273 uno_cli_env->pContext = 0;
276 //##################################################################################################
277 void SAL_CALL uno_initEnvironment( uno_Environment * uno_cli_env )
278 SAL_THROW_EXTERN_C()
280 //ToDo: remove when compiled with .NET 2
281 #if defined(_MSC_VER) && (_MSC_VER < 1400)
282 __crt_dll_initialize();
283 #endif
285 uno_cli_env->environmentDisposing= cli_env_disposing;
286 uno_cli_env->pExtEnv = 0;
287 //Set the console to print Trace messages
288 #if OSL_DEBUG_LEVEL >= 1
289 System::Diagnostics::Trace::get_Listeners()->
290 Add( new System::Diagnostics::TextWriterTraceListener(System::Console::get_Out()));
291 #endif
292 OSL_ASSERT( 0 == uno_cli_env->pContext );
294 // We let the Cli_environment leak, since there is no good point where we could destruct it.
295 //dispose is not used because we would have then also synchronize the calls to proxies. If the
296 //Cli_environment is disposed, we must prevent all calls, otherwise we may crash at points
297 //where g_cli_env is accessed.
298 //When we compile the bridge with .NET 2 then we can again hold g_cli_env as a static gcroot
299 //member in a unmanaged class, such as Bridge.
300 CliEnvHolder::g_cli_env = new Cli_environment();
302 //##################################################################################################
303 void SAL_CALL uno_ext_getMapping(
304 uno_Mapping ** ppMapping, uno_Environment * pFrom, uno_Environment * pTo )
305 SAL_THROW_EXTERN_C()
307 OSL_ASSERT( 0 != ppMapping && 0 != pFrom && 0 != pTo );
308 if (*ppMapping)
310 (*(*ppMapping)->release)( *ppMapping );
311 *ppMapping = 0;
315 OUString const & from_env_typename = *reinterpret_cast< OUString const * >(
316 &pFrom->pTypeName );
317 OUString const & to_env_typename = *reinterpret_cast< OUString const * >(
318 &pTo->pTypeName );
320 uno_Mapping * mapping = 0;
324 if ( from_env_typename == UNO_LB_CLI && to_env_typename == UNO_LB_UNO )
326 Bridge * bridge = new Bridge( pFrom, pTo->pExtEnv, true ); // ref count = 1
327 mapping = &bridge->m_cli2uno;
328 uno_registerMapping(
329 &mapping, Bridge_free, pFrom, (uno_Environment *)pTo->pExtEnv, 0 );
331 else if ( from_env_typename == UNO_LB_UNO && to_env_typename == UNO_LB_CLI )
333 Bridge * bridge = new Bridge( pTo, pFrom->pExtEnv, false ); // ref count = 1
334 mapping = &bridge->m_uno2cli;
335 uno_registerMapping(
336 &mapping, Bridge_free, (uno_Environment *)pFrom->pExtEnv, pTo, 0 );
339 catch (BridgeRuntimeError & err)
341 #if OSL_DEBUG_LEVEL >= 1
342 OString cstr_msg(
343 OUStringToOString(
344 OUSTR("[cli_uno bridge error] ") + err.m_message, RTL_TEXTENCODING_ASCII_US ) );
345 OSL_FAIL( cstr_msg.getStr() );
346 #else
347 (void) err; // unused
348 #endif
350 *ppMapping = mapping;
354 //##################################################################################################
355 SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL component_canUnload( TimeValue * )
356 SAL_THROW_EXTERN_C()
358 return true;
364 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */