Bump version to 24.04.3.4
[LibreOffice.git] / cli_ure / source / uno_bridge / cli_bridge.cxx
blobd9b4cdd0bda40706b1e0055d936fba9c3f8f58ed
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <vcclr.h>
21 #if !defined WIN32_LEAN_AND_MEAN
22 # define WIN32_LEAN_AND_MEAN
23 #endif
24 #include <windows.h>
25 #include "uno/environment.hxx"
26 #include "uno/lbnames.h"
27 #include "uno/mapping.hxx"
28 #include "typelib/typedescription.hxx"
29 #include "rtl/ustring.hxx"
30 #include <sal/log.hxx>
32 #include "cli_bridge.h"
33 #include "cli_proxy.h"
35 namespace sri= System::Runtime::InteropServices;
37 namespace cli_uno
40 extern "C"
42 void SAL_CALL Mapping_acquire( uno_Mapping * mapping )
43 SAL_THROW_EXTERN_C()
45 Mapping const * that = static_cast< Mapping const * >( mapping );
46 that->m_bridge->acquire();
49 void SAL_CALL Mapping_release( uno_Mapping * mapping )
50 SAL_THROW_EXTERN_C()
52 Mapping const * that = static_cast< Mapping const * >( mapping );
53 that->m_bridge->release();
57 void SAL_CALL Mapping_cli2uno(
58 uno_Mapping * mapping, void ** ppOut,
59 void * pIn, typelib_InterfaceTypeDescription * td )
60 SAL_THROW_EXTERN_C()
62 uno_Interface ** ppUnoI = (uno_Interface **)ppOut;
63 intptr_t cliI = (intptr_t)pIn;
65 OSL_ENSURE( ppUnoI && td, "### null ptr!" );
67 if (0 != *ppUnoI)
69 uno_Interface * pUnoI = *(uno_Interface **)ppUnoI;
70 (*pUnoI->release)( pUnoI );
71 *ppUnoI = 0;
73 try
75 Mapping const * that = static_cast< Mapping const * >( mapping );
76 Bridge * bridge = that->m_bridge;
78 if (0 != cliI)
80 System::Object^ cliObj= sri::GCHandle::FromIntPtr(IntPtr(cliI)).Target;
81 (*ppOut)= bridge->map_cli2uno(cliObj, (typelib_TypeDescription*) td);
84 catch (BridgeRuntimeError & err)
86 (void) err;
87 SAL_WARN( "cli", "[cli_uno bridge error] " << err.m_message );
91 void SAL_CALL Mapping_uno2cli(
92 uno_Mapping * mapping, void ** ppOut,
93 void * pIn, typelib_InterfaceTypeDescription * td )
94 SAL_THROW_EXTERN_C()
96 try
98 OSL_ENSURE( td && ppOut, "### null ptr!" );
99 OSL_ENSURE( (sizeof(System::Char) == sizeof(sal_Unicode))
100 && (sizeof(System::Boolean) == sizeof(sal_Bool))
101 && (sizeof(System::SByte) == sizeof(sal_Int8))
102 && (sizeof(System::Int16) == sizeof(sal_Int16))
103 && (sizeof(System::UInt16) == sizeof(sal_uInt16))
104 && (sizeof(System::Int32) == sizeof(sal_Int32))
105 && (sizeof(System::UInt32) == sizeof(sal_uInt32))
106 && (sizeof(System::Int64) == sizeof(sal_Int64))
107 && (sizeof(System::UInt64) == sizeof(sal_uInt64))
108 && (sizeof(System::Single) == sizeof(float))
109 && (sizeof(System::Double) == sizeof(double)),
110 "[cli_uno bridge] incompatible .NET data types");
111 intptr_t * ppDNetI = (intptr_t *)ppOut;
112 uno_Interface * pUnoI = (uno_Interface *)pIn;
114 Mapping const * that = static_cast< Mapping const * >( mapping );
115 Bridge * bridge = that->m_bridge;
117 if (0 != *ppDNetI)
119 sri::GCHandle::FromIntPtr(IntPtr(ppDNetI)).Free();
122 if (0 != pUnoI)
124 System::Object^ cliI= bridge->map_uno2cli(pUnoI, td);
125 intptr_t ptr= NULL;
126 if(cliI)
128 ptr= sri::GCHandle::ToIntPtr(sri::GCHandle::Alloc(cliI))
129 #ifdef _WIN64
130 .ToInt64();
131 #else /* defined(_WIN32) */
132 .ToInt32();
133 #endif
135 (*ppOut)= reinterpret_cast<void*>(ptr);
138 catch (BridgeRuntimeError & err)
140 (void) err;
141 SAL_WARN( "cli", "[cli_uno bridge error] " << err.m_message );
146 void SAL_CALL Bridge_free( uno_Mapping * mapping )
147 SAL_THROW_EXTERN_C()
149 Mapping * that = static_cast< Mapping * >( mapping );
150 delete that->m_bridge;
153 } //extern C
154 } //namespace
156 namespace cli_uno
160 /** ToDo
161 I doubt that the case that the ref count raises from 0 to 1
162 can occur. uno_ext_getMapping returns an acquired mapping. Every time
163 that function is called then a new mapping is created. Following the
164 rules of ref counted objects, then if the ref count is null no one has
165 a reference to the object anymore. Hence no one can call acquire. If someone
166 calls acquire then they must have kept an unacquired pointer which is
167 illegal.
169 void Bridge::acquire() const
171 if (1 == osl_atomic_increment( &m_ref ))
173 if (m_registered_cli2uno)
175 uno_Mapping * mapping = const_cast<Mapping*>(&m_cli2uno);
176 uno_registerMapping(
177 const_cast<uno_Mapping**>(&mapping), Bridge_free, m_uno_cli_env, (uno_Environment *)m_uno_env, 0 );
179 else
181 uno_Mapping * mapping = const_cast<Mapping*>(&m_uno2cli);
182 uno_registerMapping(
183 &mapping, Bridge_free, (uno_Environment *)m_uno_env, m_uno_cli_env, 0 );
188 void Bridge::release() const
190 if (! osl_atomic_decrement( &m_ref ))
192 uno_revokeMapping(
193 m_registered_cli2uno
194 ? const_cast<Mapping*>(&m_cli2uno)
195 : const_cast<Mapping*>(&m_uno2cli) );
199 Bridge::Bridge(
200 uno_Environment * uno_cli_env, uno_ExtEnvironment * uno_env,
201 bool registered_cli2uno )
202 : m_ref( 1 ),
203 m_uno_env( uno_env ),
204 m_uno_cli_env( uno_cli_env ),
205 m_registered_cli2uno( registered_cli2uno )
207 OSL_ASSERT( 0 != m_uno_cli_env && 0 != m_uno_env );
208 (*((uno_Environment *)m_uno_env)->acquire)( (uno_Environment *)m_uno_env );
209 (*m_uno_cli_env->acquire)( m_uno_cli_env );
211 // cli2uno
212 m_cli2uno.acquire = Mapping_acquire;
213 m_cli2uno.release = Mapping_release;
214 m_cli2uno.mapInterface = Mapping_cli2uno;
215 m_cli2uno.m_bridge = this;
216 // uno2cli
217 m_uno2cli.acquire = Mapping_acquire;
218 m_uno2cli.release = Mapping_release;
219 m_uno2cli.mapInterface = Mapping_uno2cli;
220 m_uno2cli.m_bridge = this;
225 Bridge::~Bridge()
227 //System::GC::Collect();
228 (*m_uno_cli_env->release)( m_uno_cli_env );
229 (*((uno_Environment *)m_uno_env)->release)( (uno_Environment *)m_uno_env );
233 } //namespace cli_uno
235 extern "C"
238 namespace cli_uno
241 void SAL_CALL cli_env_disposing( uno_Environment * uno_cli_env )
242 SAL_THROW_EXTERN_C()
244 uno_cli_env->pContext = 0;
248 SAL_DLLPUBLIC_EXPORT void SAL_CALL uno_initEnvironment( uno_Environment * uno_cli_env )
249 SAL_THROW_EXTERN_C()
251 //ToDo: remove when compiled with .NET 2
253 // Unclear whether the above comment refers to this whole function
254 // or a call to __crt_dll_initialize() that used to be here for
255 // _MSC_VER < 1400
257 uno_cli_env->environmentDisposing= cli_env_disposing;
258 uno_cli_env->pExtEnv = 0;
259 //Set the console to print Trace messages
260 #if OSL_DEBUG_LEVEL >= 1
261 System::Diagnostics::Trace::Listeners->
262 Add( gcnew System::Diagnostics::TextWriterTraceListener(System::Console::Out));
263 #endif
264 OSL_ASSERT( 0 == uno_cli_env->pContext );
266 // We let the Cli_environment leak, since there is no good point where we could destruct it.
267 //dispose is not used because we would have then also synchronize the calls to proxies. If the
268 //Cli_environment is disposed, we must prevent all calls, otherwise we may crash at points
269 //where g_cli_env is accessed.
270 //When we compile the bridge with .NET 2 then we can again hold g_cli_env as a static gcroot
271 //member in a unmanaged class, such as Bridge.
272 CliEnvHolder::g_cli_env = gcnew Cli_environment();
275 SAL_DLLPUBLIC_EXPORT void SAL_CALL uno_ext_getMapping(
276 uno_Mapping ** ppMapping, uno_Environment * pFrom, uno_Environment * pTo )
277 SAL_THROW_EXTERN_C()
279 OSL_ASSERT( 0 != ppMapping && 0 != pFrom && 0 != pTo );
280 if (*ppMapping)
282 (*(*ppMapping)->release)( *ppMapping );
283 *ppMapping = 0;
287 OUString const & from_env_typename = OUString::unacquired(
288 &pFrom->pTypeName );
289 OUString const & to_env_typename = OUString::unacquired( &pTo->pTypeName );
291 uno_Mapping * mapping = 0;
295 if ( from_env_typename == UNO_LB_CLI && to_env_typename == UNO_LB_UNO )
297 Bridge * bridge = new Bridge( pFrom, pTo->pExtEnv, true ); // ref count = 1
298 mapping = &bridge->m_cli2uno;
299 uno_registerMapping(
300 &mapping, Bridge_free, pFrom, (uno_Environment *)pTo->pExtEnv, 0 );
302 else if ( from_env_typename == UNO_LB_UNO && to_env_typename == UNO_LB_CLI )
304 Bridge * bridge = new Bridge( pTo, pFrom->pExtEnv, false ); // ref count = 1
305 mapping = &bridge->m_uno2cli;
306 uno_registerMapping(
307 &mapping, Bridge_free, (uno_Environment *)pFrom->pExtEnv, pTo, 0 );
310 catch (BridgeRuntimeError & err)
312 (void) err;
313 SAL_WARN( "cli", "[cli_uno bridge error] " << err.m_message );
315 *ppMapping = mapping;
321 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */