1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
21 //ToDo: remove when build with .NET 2
22 #pragma warning(push, 1)
24 #include "uno/environment.hxx"
26 #include "uno/lbnames.h"
27 #include "uno/mapping.hxx"
28 #include "typelib/typedescription.hxx"
29 #include "rtl/ustring.hxx"
31 #include "cli_bridge.h"
32 #include "cli_proxy.h"
34 namespace sri
= System::Runtime::InteropServices
;
41 void SAL_CALL
Mapping_acquire( uno_Mapping
* mapping
)
44 Mapping
const * that
= static_cast< Mapping
const * >( mapping
);
45 that
->m_bridge
->acquire();
47 //--------------------------------------------------------------------------------------------------
48 void SAL_CALL
Mapping_release( uno_Mapping
* mapping
)
51 Mapping
const * that
= static_cast< Mapping
const * >( mapping
);
52 that
->m_bridge
->release();
56 //--------------------------------------------------------------------------------------------------
57 void SAL_CALL
Mapping_cli2uno(
58 uno_Mapping
* mapping
, void ** ppOut
,
59 void * pIn
, typelib_InterfaceTypeDescription
* td
)
62 uno_Interface
** ppUnoI
= (uno_Interface
**)ppOut
;
63 intptr_t cliI
= (intptr_t)pIn
;
65 OSL_ENSURE( ppUnoI
&& td
, "### null ptr!" );
69 uno_Interface
* pUnoI
= *(uno_Interface
**)ppUnoI
;
70 (*pUnoI
->release
)( pUnoI
);
75 Mapping
const * that
= static_cast< Mapping
const * >( mapping
);
76 Bridge
* bridge
= that
->m_bridge
;
80 System::Object
^ cliObj
= sri::GCHandle::FromIntPtr(IntPtr(cliI
)).Target
;
81 (*ppOut
)= bridge
->map_cli2uno(cliObj
, (typelib_TypeDescription
*) td
);
84 catch (BridgeRuntimeError
& err
)
86 #if OSL_DEBUG_LEVEL >= 1
89 "[cli_uno bridge error] " + err
.m_message
, RTL_TEXTENCODING_ASCII_US
) );
90 OSL_FAIL( cstr_msg
.getStr() );
96 //--------------------------------------------------------------------------------------------------
97 void SAL_CALL
Mapping_uno2cli(
98 uno_Mapping
* mapping
, void ** ppOut
,
99 void * pIn
, typelib_InterfaceTypeDescription
* td
)
104 OSL_ENSURE( td
&& ppOut
, "### null ptr!" );
105 OSL_ENSURE( (sizeof(System::Char
) == sizeof(sal_Unicode
))
106 && (sizeof(System::Boolean
) == sizeof(sal_Bool
))
107 && (sizeof(System::SByte
) == sizeof(sal_Int8
))
108 && (sizeof(System::Int16
) == sizeof(sal_Int16
))
109 && (sizeof(System::UInt16
) == sizeof(sal_uInt16
))
110 && (sizeof(System::Int32
) == sizeof(sal_Int32
))
111 && (sizeof(System::UInt32
) == sizeof(sal_uInt32
))
112 && (sizeof(System::Int64
) == sizeof(sal_Int64
))
113 && (sizeof(System::UInt64
) == sizeof(sal_uInt64
))
114 && (sizeof(System::Single
) == sizeof(float))
115 && (sizeof(System::Double
) == sizeof(double)),
116 "[cli_uno bridge] incompatible .NET data types");
117 intptr_t * ppDNetI
= (intptr_t *)ppOut
;
118 uno_Interface
* pUnoI
= (uno_Interface
*)pIn
;
120 Mapping
const * that
= static_cast< Mapping
const * >( mapping
);
121 Bridge
* bridge
= that
->m_bridge
;
125 sri::GCHandle::FromIntPtr(IntPtr(ppDNetI
)).Free();
130 System::Object
^ cliI
= bridge
->map_uno2cli(pUnoI
, td
);
134 ptr
= sri::GCHandle::ToIntPtr(sri::GCHandle::Alloc(cliI
))
137 #else /* defined(_WIN64) */ .ToInt64();
140 (*ppOut
)= reinterpret_cast<void*>(ptr
);
143 catch (BridgeRuntimeError
& err
)
145 #if OSL_DEBUG_LEVEL >= 1
148 "[cli_uno bridge error] " + err
.m_message
, RTL_TEXTENCODING_ASCII_US
) );
149 OSL_FAIL( cstr_msg
.getStr() );
151 (void) err
; // unused
156 //__________________________________________________________________________________________________
157 void SAL_CALL
Bridge_free( uno_Mapping
* mapping
)
160 Mapping
* that
= static_cast< Mapping
* >( mapping
);
161 delete that
->m_bridge
;
170 //__________________________________________________________________________________________________
172 I doubt that the case that the ref count raises from 0 to 1
173 can occur. uno_ext_getMapping returns an acquired mapping. Every time
174 that function is called then a new mapping is created. Following the
175 rules of ref counted objects, then if the ref count is null noone has
176 a reference to the object anymore. Hence noone can call acquire. If someone
177 calls acquire then they must have kept an unacquired pointer which is
180 void Bridge::acquire() const SAL_THROW(())
182 if (1 == osl_atomic_increment( &m_ref
))
184 if (m_registered_cli2uno
)
186 uno_Mapping
* mapping
= const_cast<Mapping
*>(&m_cli2uno
);
188 & const_cast<uno_Mapping
*>(mapping
), Bridge_free
, m_uno_cli_env
, (uno_Environment
*)m_uno_env
, 0 );
192 uno_Mapping
* mapping
= const_cast<Mapping
*>(&m_uno2cli
);
194 &mapping
, Bridge_free
, (uno_Environment
*)m_uno_env
, m_uno_cli_env
, 0 );
198 //__________________________________________________________________________________________________
199 void Bridge::release() const SAL_THROW(())
201 if (! osl_atomic_decrement( &m_ref
))
205 ? const_cast<Mapping
*>(&m_cli2uno
)
206 : const_cast<Mapping
*>(&m_uno2cli
) );
209 //__________________________________________________________________________________________________
211 uno_Environment
* uno_cli_env
, uno_ExtEnvironment
* uno_env
,
212 bool registered_cli2uno
)
214 m_uno_env( uno_env
),
215 m_uno_cli_env( uno_cli_env
),
216 m_registered_cli2uno( registered_cli2uno
)
218 OSL_ASSERT( 0 != m_uno_cli_env
&& 0 != m_uno_env
);
219 (*((uno_Environment
*)m_uno_env
)->acquire
)( (uno_Environment
*)m_uno_env
);
220 (*m_uno_cli_env
->acquire
)( m_uno_cli_env
);
223 m_cli2uno
.acquire
= Mapping_acquire
;
224 m_cli2uno
.release
= Mapping_release
;
225 m_cli2uno
.mapInterface
= Mapping_cli2uno
;
226 m_cli2uno
.m_bridge
= this;
228 m_uno2cli
.acquire
= Mapping_acquire
;
229 m_uno2cli
.release
= Mapping_release
;
230 m_uno2cli
.mapInterface
= Mapping_uno2cli
;
231 m_uno2cli
.m_bridge
= this;
235 //__________________________________________________________________________________________________
236 Bridge::~Bridge() SAL_THROW(())
238 //System::GC::Collect();
239 (*m_uno_cli_env
->release
)( m_uno_cli_env
);
240 (*((uno_Environment
*)m_uno_env
)->release
)( (uno_Environment
*)m_uno_env
);
245 } //namespace cli_uno
252 //--------------------------------------------------------------------------------------------------
253 void SAL_CALL
cli_env_disposing( uno_Environment
* uno_cli_env
)
256 uno_cli_env
->pContext
= 0;
259 //##################################################################################################
260 SAL_DLLPUBLIC_EXPORT
void SAL_CALL
uno_initEnvironment( uno_Environment
* uno_cli_env
)
263 //ToDo: remove when compiled with .NET 2
265 // Unclear whether the above comment refers to this whole function
266 // or a call to __crt_dll_initialize() that used to be here for
269 uno_cli_env
->environmentDisposing
= cli_env_disposing
;
270 uno_cli_env
->pExtEnv
= 0;
271 //Set the console to print Trace messages
272 #if OSL_DEBUG_LEVEL >= 1
273 System::Diagnostics::Trace::Listeners
->
274 Add( gcnew
System::Diagnostics::TextWriterTraceListener(System::Console::Out
));
276 OSL_ASSERT( 0 == uno_cli_env
->pContext
);
278 // We let the Cli_environment leak, since there is no good point where we could destruct it.
279 //dispose is not used because we would have then also synchronize the calls to proxies. If the
280 //Cli_environment is disposed, we must prevent all calls, otherwise we may crash at points
281 //where g_cli_env is accessed.
282 //When we compile the bridge with .NET 2 then we can again hold g_cli_env as a static gcroot
283 //member in a unmanaged class, such as Bridge.
284 CliEnvHolder::g_cli_env
= gcnew
Cli_environment();
286 //##################################################################################################
287 SAL_DLLPUBLIC_EXPORT
void SAL_CALL
uno_ext_getMapping(
288 uno_Mapping
** ppMapping
, uno_Environment
* pFrom
, uno_Environment
* pTo
)
291 OSL_ASSERT( 0 != ppMapping
&& 0 != pFrom
&& 0 != pTo
);
294 (*(*ppMapping
)->release
)( *ppMapping
);
299 OUString
const & from_env_typename
= *reinterpret_cast< OUString
const * >(
301 OUString
const & to_env_typename
= *reinterpret_cast< OUString
const * >(
304 uno_Mapping
* mapping
= 0;
308 if ( from_env_typename
== UNO_LB_CLI
&& to_env_typename
== UNO_LB_UNO
)
310 Bridge
* bridge
= new Bridge( pFrom
, pTo
->pExtEnv
, true ); // ref count = 1
311 mapping
= &bridge
->m_cli2uno
;
313 &mapping
, Bridge_free
, pFrom
, (uno_Environment
*)pTo
->pExtEnv
, 0 );
315 else if ( from_env_typename
== UNO_LB_UNO
&& to_env_typename
== UNO_LB_CLI
)
317 Bridge
* bridge
= new Bridge( pTo
, pFrom
->pExtEnv
, false ); // ref count = 1
318 mapping
= &bridge
->m_uno2cli
;
320 &mapping
, Bridge_free
, (uno_Environment
*)pFrom
->pExtEnv
, pTo
, 0 );
323 catch (BridgeRuntimeError
& err
)
325 #if OSL_DEBUG_LEVEL >= 1
328 "[cli_uno bridge error] " + err
.m_message
, RTL_TEXTENCODING_ASCII_US
) );
329 OSL_FAIL( cstr_msg
.getStr() );
331 (void) err
; // unused
334 *ppMapping
= mapping
;
340 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */