LibreOffice Module cli_ure (master) 1
cli_bridge.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
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>
31
32#include "cli_bridge.h"
33#include "cli_proxy.h"
34
35namespace sri= System::Runtime::InteropServices;
36
37namespace cli_uno
38{
39
40extern "C"
41{
42void SAL_CALL Mapping_acquire( uno_Mapping * mapping )
44{
45 Mapping const * that = static_cast< Mapping const * >( mapping );
46 that->m_bridge->acquire();
47}
48
49void SAL_CALL Mapping_release( uno_Mapping * mapping )
51{
52 Mapping const * that = static_cast< Mapping const * >( mapping );
53 that->m_bridge->release();
54}
55
56
57void SAL_CALL Mapping_cli2uno(
58 uno_Mapping * mapping, void ** ppOut,
59 void * pIn, typelib_InterfaceTypeDescription * td )
61{
62 uno_Interface ** ppUnoI = (uno_Interface **)ppOut;
63 intptr_t cliI = (intptr_t)pIn;
64
65 OSL_ENSURE( ppUnoI && td, "### null ptr!" );
66
67 if (0 != *ppUnoI)
68 {
69 uno_Interface * pUnoI = *(uno_Interface **)ppUnoI;
70 (*pUnoI->release)( pUnoI );
71 *ppUnoI = 0;
72 }
73 try
74 {
75 Mapping const * that = static_cast< Mapping const * >( mapping );
76 Bridge * bridge = that->m_bridge;
77
78 if (0 != cliI)
79 {
80 System::Object^ cliObj= sri::GCHandle::FromIntPtr(IntPtr(cliI)).Target;
81 (*ppOut)= bridge->map_cli2uno(cliObj, (typelib_TypeDescription*) td);
82 }
83 }
84 catch (BridgeRuntimeError & err)
85 {
86 (void) err;
87 SAL_WARN( "cli", "[cli_uno bridge error] " << err.m_message );
88 }
89}
90
91void SAL_CALL Mapping_uno2cli(
92 uno_Mapping * mapping, void ** ppOut,
93 void * pIn, typelib_InterfaceTypeDescription * td )
95{
96 try
97 {
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;
113
114 Mapping const * that = static_cast< Mapping const * >( mapping );
115 Bridge * bridge = that->m_bridge;
116
117 if (0 != *ppDNetI)
118 {
119 sri::GCHandle::FromIntPtr(IntPtr(ppDNetI)).Free();
120 }
121
122 if (0 != pUnoI)
123 {
124 System::Object^ cliI= bridge->map_uno2cli(pUnoI, td);
125 intptr_t ptr= NULL;
126 if(cliI)
127 {
128 ptr= sri::GCHandle::ToIntPtr(sri::GCHandle::Alloc(cliI))
129#ifdef _WIN64
130 .ToInt64();
131#else /* defined(_WIN32) */
132 .ToInt32();
133#endif
134 }
135 (*ppOut)= reinterpret_cast<void*>(ptr);
136 }
137 }
138 catch (BridgeRuntimeError & err)
139 {
140 (void) err;
141 SAL_WARN( "cli", "[cli_uno bridge error] " << err.m_message );
142 }
143}
144
145
146void SAL_CALL Bridge_free( uno_Mapping * mapping )
148{
149 Mapping * that = static_cast< Mapping * >( mapping );
150 delete that->m_bridge;
151}
152
153} //extern C
154} //namespace
155
156namespace cli_uno
157{
158
159
169void Bridge::acquire() const
170{
171 if (1 == osl_atomic_increment( &m_ref ))
172 {
174 {
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 );
178 }
179 else
180 {
181 uno_Mapping * mapping = const_cast<Mapping*>(&m_uno2cli);
184 }
185 }
186}
187
188void Bridge::release() const
189{
190 if (! osl_atomic_decrement( &m_ref ))
191 {
194 ? const_cast<Mapping*>(&m_cli2uno)
195 : const_cast<Mapping*>(&m_uno2cli) );
196 }
197}
198
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 )
206{
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 );
210
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;
221
222}
223
224
226{
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 );
230}
231
232
233} //namespace cli_uno
234
235extern "C"
236{
237
238namespace cli_uno
239{
240
241void SAL_CALL cli_env_disposing( uno_Environment * uno_cli_env )
243{
244 uno_cli_env->pContext = 0;
245}
246
247
248SAL_DLLPUBLIC_EXPORT void SAL_CALL uno_initEnvironment( uno_Environment * uno_cli_env )
250{
251 //ToDo: remove when compiled with .NET 2
252
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
256
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 );
265
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.
273}
274
275SAL_DLLPUBLIC_EXPORT void SAL_CALL uno_ext_getMapping(
276 uno_Mapping ** ppMapping, uno_Environment * pFrom, uno_Environment * pTo )
278{
279 OSL_ASSERT( 0 != ppMapping && 0 != pFrom && 0 != pTo );
280 if (*ppMapping)
281 {
282 (*(*ppMapping)->release)( *ppMapping );
283 *ppMapping = 0;
284 }
285
286
287 OUString const & from_env_typename = OUString::unacquired(
288 &pFrom->pTypeName );
289 OUString const & to_env_typename = OUString::unacquired( &pTo->pTypeName );
290
291 uno_Mapping * mapping = 0;
292
293 try
294 {
295 if ( from_env_typename == UNO_LB_CLI && to_env_typename == UNO_LB_UNO )
296 {
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 );
301 }
302 else if ( from_env_typename == UNO_LB_UNO && to_env_typename == UNO_LB_CLI )
303 {
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 );
308 }
309 }
310 catch (BridgeRuntimeError & err)
311 {
312 (void) err;
313 SAL_WARN( "cli", "[cli_uno bridge error] " << err.m_message );
314 }
315 *ppMapping = mapping;
316}
317
318}
319}
320
321/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
struct _uno_Environment uno_Environment
std::atomic< std::size_t > m_ref
void SAL_CALL uno_registerMapping(uno_Mapping **ppMapping, uno_freeMappingFunc freeMapping, uno_Environment *pFrom, uno_Environment *pTo, rtl_uString *pAddPurpose) SAL_THROW_EXTERN_C()
void SAL_CALL uno_revokeMapping(uno_Mapping *pMapping) SAL_THROW_EXTERN_C()
#define SAL_WARN(area, stream)
return NULL
struct _uno_Mapping uno_Mapping
struct _typelib_TypeDescription typelib_TypeDescription
err
void SAL_CALL Mapping_acquire(uno_Mapping *mapping) SAL_THROW_EXTERN_C()
Definition: cli_bridge.cxx:42
void SAL_CALL Mapping_release(uno_Mapping *mapping) SAL_THROW_EXTERN_C()
Definition: cli_bridge.cxx:49
void SAL_CALL Mapping_uno2cli(uno_Mapping *mapping, void **ppOut, void *pIn, typelib_InterfaceTypeDescription *td) SAL_THROW_EXTERN_C()
Definition: cli_bridge.cxx:91
void SAL_CALL Bridge_free(uno_Mapping *mapping) SAL_THROW_EXTERN_C()
Definition: cli_bridge.cxx:146
SAL_DLLPUBLIC_EXPORT void SAL_CALL uno_initEnvironment(uno_Environment *uno_cli_env) SAL_THROW_EXTERN_C()
Definition: cli_bridge.cxx:248
void SAL_CALL Mapping_cli2uno(uno_Mapping *mapping, void **ppOut, void *pIn, typelib_InterfaceTypeDescription *td) SAL_THROW_EXTERN_C()
Definition: cli_bridge.cxx:57
void SAL_CALL cli_env_disposing(uno_Environment *uno_cli_env) SAL_THROW_EXTERN_C()
Definition: cli_bridge.cxx:241
SAL_DLLPUBLIC_EXPORT void SAL_CALL uno_ext_getMapping(uno_Mapping **ppMapping, uno_Environment *pFrom, uno_Environment *pTo) SAL_THROW_EXTERN_C()
Definition: cli_bridge.cxx:275
An instance of Bridge represents exactly one mapping therefore either m_cli2uno or m_uno2cli is valid...
Definition: cli_bridge.h:58
Mapping m_cli2uno
Definition: cli_bridge.h:63
System::Object map_uno2cli(uno_Interface *pUnoI, typelib_InterfaceTypeDescription *pTD) const
Definition: cli_data.cxx:63
oslInterlockedCount m_ref
Definition: cli_bridge.h:59
uno_Environment * m_uno_cli_env
Definition: cli_bridge.h:61
Mapping m_uno2cli
Definition: cli_bridge.h:64
Bridge(uno_Environment *java_env, uno_ExtEnvironment *uno_env, bool registered_java2uno)
Definition: cli_bridge.cxx:199
void release() const
Definition: cli_bridge.cxx:188
uno_ExtEnvironment * m_uno_env
Definition: cli_bridge.h:60
uno_Interface * map_cli2uno(System::Object^ cliI, typelib_TypeDescription *pTD) const
Definition: cli_data.cxx:107
void acquire() const
ToDo I doubt that the case that the ref count raises from 0 to 1 can occur.
Definition: cli_bridge.cxx:169
bool m_registered_cli2uno
Definition: cli_bridge.h:65
static Cli_environment g_cli_env
Definition: cli_bridge.h:50
Bridge * m_bridge
Definition: cli_bridge.h:43
unsigned char sal_Bool
#define SAL_THROW_EXTERN_C()
sal_uInt16 sal_Unicode
signed char sal_Int8