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 #if !defined WIN32_LEAN_AND_MEAN
22 # define WIN32_LEAN_AND_MEAN
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
;
42 void SAL_CALL
Mapping_acquire( uno_Mapping
* mapping
)
45 Mapping
const * that
= static_cast< Mapping
const * >( mapping
);
46 that
->m_bridge
->acquire();
49 void SAL_CALL
Mapping_release( uno_Mapping
* mapping
)
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
)
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
)
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
)
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
;
119 sri::GCHandle::FromIntPtr(IntPtr(ppDNetI
)).Free();
124 System::Object
^ cliI
= bridge
->map_uno2cli(pUnoI
, td
);
128 ptr
= sri::GCHandle::ToIntPtr(sri::GCHandle::Alloc(cliI
))
131 #else /* defined(_WIN32) */
135 (*ppOut
)= reinterpret_cast<void*>(ptr
);
138 catch (BridgeRuntimeError
& err
)
141 SAL_WARN( "cli", "[cli_uno bridge error] " << err
.m_message
);
146 void SAL_CALL
Bridge_free( uno_Mapping
* mapping
)
149 Mapping
* that
= static_cast< Mapping
* >( mapping
);
150 delete that
->m_bridge
;
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
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
);
177 const_cast<uno_Mapping
**>(&mapping
), Bridge_free
, m_uno_cli_env
, (uno_Environment
*)m_uno_env
, 0 );
181 uno_Mapping
* mapping
= const_cast<Mapping
*>(&m_uno2cli
);
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
))
194 ? const_cast<Mapping
*>(&m_cli2uno
)
195 : const_cast<Mapping
*>(&m_uno2cli
) );
200 uno_Environment
* uno_cli_env
, uno_ExtEnvironment
* uno_env
,
201 bool registered_cli2uno
)
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
);
212 m_cli2uno
.acquire
= Mapping_acquire
;
213 m_cli2uno
.release
= Mapping_release
;
214 m_cli2uno
.mapInterface
= Mapping_cli2uno
;
215 m_cli2uno
.m_bridge
= this;
217 m_uno2cli
.acquire
= Mapping_acquire
;
218 m_uno2cli
.release
= Mapping_release
;
219 m_uno2cli
.mapInterface
= Mapping_uno2cli
;
220 m_uno2cli
.m_bridge
= this;
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
241 void SAL_CALL
cli_env_disposing( uno_Environment
* uno_cli_env
)
244 uno_cli_env
->pContext
= 0;
248 SAL_DLLPUBLIC_EXPORT
void SAL_CALL
uno_initEnvironment( uno_Environment
* uno_cli_env
)
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
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
));
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
)
279 OSL_ASSERT( 0 != ppMapping
&& 0 != pFrom
&& 0 != pTo
);
282 (*(*ppMapping
)->release
)( *ppMapping
);
287 OUString
const & from_env_typename
= OUString::unacquired(
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
;
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
;
307 &mapping
, Bridge_free
, (uno_Environment
*)pFrom
->pExtEnv
, pTo
, 0 );
310 catch (BridgeRuntimeError
& err
)
313 SAL_WARN( "cli", "[cli_uno bridge error] " << err
.m_message
);
315 *ppMapping
= mapping
;
321 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */