update dev300-m58
[ooovba.git] / cli_ure / source / mono_bridge / mono_bridge.cxx
blob748fc5e533f9fad9cebee8a5169c394f07bfbbd0
1 /*************************************************************************
3 * $RCSfile: $
5 * $Revision: $
7 * last change: $Author: $ $Date: $
9 * The Contents of this file are made available subject to the terms of
10 * either of the following licenses
12 * - GNU Lesser General Public License Version 2.1
13 * - Sun Industry Standards Source License Version 1.1
15 * Sun Microsystems Inc., October, 2000
17 * GNU Lesser General Public License Version 2.1
18 * =============================================
19 * Copyright 2000 by Sun Microsystems, Inc.
20 * 901 San Antonio Road, Palo Alto, CA 94303, USA
22 * This library is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU Lesser General Public
24 * License version 2.1, as published by the Free Software Foundation.
26 * This library is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
29 * Lesser General Public License for more details.
31 * You should have received a copy of the GNU Lesser General Public
32 * License along with this library; if not, write to the Free Software
33 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
34 * MA 02111-1307 USA
37 * Sun Industry Standards Source License Version 1.1
38 * =================================================
39 * The contents of this file are subject to the Sun Industry Standards
40 * Source License Version 1.1 (the "License"); You may not use this file
41 * except in compliance with the License. You may obtain a copy of the
42 * License at http://www.openoffice.org/license.html.
44 * Software provided under this License is provided on an "AS IS" basis,
45 * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
46 * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
47 * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
48 * See the License for the specific provisions governing your rights and
49 * obligations concerning the Software.
51 * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
53 * Copyright: 2000 by Sun Microsystems, Inc.
55 * All Rights Reserved.
57 * Contributor(s): _______________________________________
60 ************************************************************************/
62 #include <string.h>
64 #include "uno/dispatcher.h"
65 #include "uno/environment.h"
66 #include "uno/lbnames.h"
68 #include "osl/diagnose.h"
69 #include "rtl/unload.h"
70 #include "rtl/ustring.hxx"
72 #include "uno/mapping.hxx"
74 extern "C" {
75 #include "mono/metadata/appdomain.h"
76 #include "mono/metadata/assembly.h"
77 #include "mono/metadata/debug-helpers.h"
78 #include "mono/metadata/object.h"
79 #include "mono/metadata/threads.h"
82 #include "mono_bridge.h"
84 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
86 using namespace ::rtl;
87 using namespace ::mono_uno;
89 extern "C" {
91 void SAL_CALL Mapping_acquire( uno_Mapping * mapping )
92 SAL_THROW_EXTERN_C()
94 static_cast< Mapping const * >( mapping )->m_bridge->acquire();
97 void SAL_CALL Mapping_release( uno_Mapping * mapping )
98 SAL_THROW_EXTERN_C()
100 static_cast< Mapping const * >( mapping )->m_bridge->release();
103 void SAL_CALL Mapping_map_to_uno(
104 uno_Mapping * mapping, void ** ppOut,
105 void * pIn, typelib_InterfaceTypeDescription * td )
106 SAL_THROW_EXTERN_C()
108 uno_Interface ** ppUnoI = (uno_Interface **)ppOut;
109 void * monoI = pIn;
111 // FIXME do this here? OSL_ASSERT( sizeof (void *) >= sizeof (guint32))
112 OSL_ENSURE( ppUnoI && td, "### null ptr!" );
114 if (0 != *ppUnoI)
116 uno_Interface * pUnoI = *ppUnoI;
117 (*pUnoI->release)( pUnoI );
118 *ppUnoI = 0;
123 Bridge const *bridge =
124 static_cast< Mapping const * >( mapping )->m_bridge;
125 // FIXME any wrapper necessary around mono calls? cf. JNI_guarded_context
126 uno_Interface * pUnoI = bridge->map_to_uno(
127 monoI, (typelib_TypeDescription *)td );
128 *ppUnoI = pUnoI;
130 catch (BridgeRuntimeError & err)
132 #if OSL_DEBUG_LEVEL > 0
133 OString cstr_msg(
134 OUStringToOString(
135 OUSTR("[mono_uno bridge error] ") + err.m_message,
136 RTL_TEXTENCODING_ASCII_US ) );
137 OSL_ENSURE( 0, cstr_msg.getStr() );
138 #endif
142 void SAL_CALL Mapping_map_to_mono(
143 uno_Mapping * mapping, void ** ppOut,
144 void * pIn, typelib_InterfaceTypeDescription * td )
145 SAL_THROW_EXTERN_C()
147 void ** pMonoI = ppOut;
148 uno_Interface * pUnoI = (uno_Interface *)pIn;
150 OSL_ENSURE( ppOut && td, "### null ptr!" );
152 if (0 != *pMonoI)
154 // FIXME JNI bridge has guarded_context here
155 // FIXME: do the right thing in the managed bridge
156 // mono_gchandle_free( *pMonoI );
161 if (0 != pUnoI)
163 Bridge const * bridge =
164 static_cast< Mapping const *>( mapping )->m_bridge;
165 // FIXME guarded context
166 *ppOut = (void *)bridge->map_to_mono(
167 pUnoI, (typelib_TypeDescription *)td );
168 OSL_ASSERT( ppOut && *ppOut );
171 catch (BridgeRuntimeError & err)
173 #if OSL_DEBUG_LEVEL >= 1
174 rtl::OString cstr_msg(
175 rtl::OUStringToOString(
176 OUSTR("[mono_uno bridge error] ") + err.m_message,
177 RTL_TEXTENCODING_ASCII_US ) );
178 OSL_ENSURE( 0, cstr_msg.getStr() );
179 #endif
183 void SAL_CALL Bridge_free( uno_Mapping * mapping )
184 SAL_THROW_EXTERN_C()
186 Mapping * that = static_cast< Mapping * >( mapping );
187 delete that->m_bridge;
190 } // extern "C"
192 rtl_StandardModuleCount g_moduleCount = MODULE_COUNT_INIT;
194 namespace mono_uno
197 void Bridge::acquire() const SAL_THROW( () )
199 if (1 == osl_incrementInterlockedCount( &m_ref ))
201 if (m_registered_mono2uno)
203 uno_Mapping * mapping = const_cast< Mapping * >( &m_mono2uno );
204 uno_registerMapping(
205 &mapping, Bridge_free,
206 m_mono_env, (uno_Environment *)m_uno_env, 0 );
208 else
210 uno_Mapping * mapping = const_cast< Mapping * >( &m_uno2mono );
211 uno_registerMapping(
212 &mapping, Bridge_free,
213 (uno_Environment *)m_uno_env, m_mono_env, 0 );
218 void Bridge::release() const SAL_THROW( () )
220 if (! osl_decrementInterlockedCount( &m_ref ))
222 uno_revokeMapping(
223 m_registered_mono2uno
224 ? const_cast< Mapping * >( &m_mono2uno )
225 : const_cast< Mapping * >( &m_uno2mono ) );
229 MonoAssembly *
230 DoLoad (MonoDomain *domain, char *fullname)
232 MonoAssemblyName aname;
233 MonoImageOpenStatus status;
234 MonoAssembly *ass;
236 memset (&aname, 0, sizeof (aname));
237 aname.culture = "";
238 strncpy ((char *)aname.public_key_token, "ce2cb7e279207b9e", MONO_PUBLIC_KEY_TOKEN_LENGTH);
239 aname.name = "cli_uno_bridge";
240 aname.major=1;
241 aname.minor=0;
242 aname.build=0;
243 aname.revision=0;
245 ass = mono_assembly_load (&aname, NULL, &status);
246 if (status != MONO_IMAGE_OK)
247 return NULL;
248 return ass;
251 Bridge::Bridge(
252 uno_Environment * mono_env, uno_ExtEnvironment * uno_env,
253 bool registered_mono2uno )
254 : m_ref( 1 ),
255 m_uno_env( uno_env ),
256 m_mono_env( mono_env ),
257 m_registered_mono2uno( registered_mono2uno )
259 MonoDomain * pDomain = mono_get_root_domain();
260 // FIXME where is this freed?
261 MonoAssembly * pAssembly = DoLoad (pDomain, "cli_uno_bridge, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce2cb7e279207b9e");
262 // FIXME and this, is this needed later?
263 MonoClass * pClass = mono_class_from_name (
264 (MonoImage *)mono_assembly_get_image( pAssembly ), "com.sun.star.bridges.mono_uno", "Bridge" );
265 OSL_ASSERT( 0 != pClass );
266 /* FIXME add args to method description string */
267 MonoMethodDesc * pMethodDesc = mono_method_desc_new( ":.ctor", FALSE );
268 MonoMethod * pCtor = mono_method_desc_search_in_class( pMethodDesc, pClass );
269 mono_method_desc_free( pMethodDesc );
270 OSL_ASSERT( 0 != pCtor );
272 pMethodDesc = mono_method_desc_new( "Bridge:MapManagedToUno", FALSE );
273 m_mapManagedToUnoMethod = mono_method_desc_search_in_class( pMethodDesc, pClass );
274 mono_method_desc_free( pMethodDesc );
275 OSL_ASSERT( 0 != m_mapManagedToUnoMethod );
277 pMethodDesc = mono_method_desc_new( "Bridge:MapUnoToManaged", FALSE );
278 m_mapUnoToManagedMethod = mono_method_desc_search_in_class( pMethodDesc, pClass );
279 mono_method_desc_free( pMethodDesc );
280 OSL_ASSERT( 0 != m_mapUnoToManagedMethod );
282 gpointer pParams[1];
283 pParams[0] = &uno_env;
284 m_managedBridge = mono_object_new( pDomain, pClass );
285 mono_uno::runtime_invoke( pCtor, m_managedBridge, pParams, NULL,
286 mono_object_get_domain( m_managedBridge ) );
288 OSL_ASSERT( 0 != m_mono_env && 0 != m_uno_env );
289 (*((uno_Environment *)m_uno_env)->acquire)( (uno_Environment *)m_uno_env );
290 (*m_mono_env->acquire)( m_mono_env );
292 // mono2uno mapping
293 m_mono2uno.acquire = Mapping_acquire;
294 m_mono2uno.release = Mapping_release;
295 m_mono2uno.mapInterface = Mapping_map_to_uno;
296 m_mono2uno.m_bridge = this;
297 // uno2mono mapping
298 m_uno2mono.acquire = Mapping_acquire;
299 m_uno2mono.release = Mapping_release;
300 m_uno2mono.mapInterface = Mapping_map_to_mono;
301 m_uno2mono.m_bridge = this;
303 (*g_moduleCount.modCnt.acquire)( &g_moduleCount.modCnt );
306 Bridge::~Bridge() SAL_THROW( () )
308 (*m_mono_env->release)( m_mono_env );
309 (*((uno_Environment *)m_uno_env)->release)( (uno_Environment *)m_uno_env );
310 // FIXME release managed bridge
312 (*g_moduleCount.modCnt.release)( &g_moduleCount.modCnt );
315 void * Bridge::map_to_mono(
316 uno_Interface *pUnoI, typelib_TypeDescription * pTD ) const
318 gpointer pMonoParams[2];
320 pMonoParams[0] = &pUnoI;
321 pMonoParams[1] = pTD;
323 return
324 mono_uno::runtime_invoke( m_mapUnoToManagedMethod,
325 m_managedBridge, pMonoParams, NULL,
326 mono_object_get_domain( m_managedBridge ) );
329 uno_Interface * Bridge::map_to_uno(
330 void * pMonoI, typelib_TypeDescription * pTD ) const
332 gpointer pMonoParams[2];
333 uno_Interface ** ppResult;
335 pMonoParams[0] = pMonoI;
336 pMonoParams[1] = pTD;
338 ppResult = (uno_Interface **)mono_object_unbox(
339 mono_uno::runtime_invoke( m_mapManagedToUnoMethod,
340 m_managedBridge, pMonoParams, NULL,
341 mono_object_get_domain( m_managedBridge ) ) );
343 return *ppResult;
346 } // namespace mono_uno
348 extern "C" {
350 // void SAL_CALL mono_environmentDisposing( uno_Environment * mono_env )
351 // SAL_THROW_EXTERN_C()
352 // {
353 // }
355 void SAL_CALL uno_initEnvironment( uno_Environment * mono_env )
356 SAL_THROW_EXTERN_C()
358 // mono_env->environmentDisposing = mono_environmentDisposing;
359 mono_env->pExtEnv = 0; /* no extended support */
362 void SAL_CALL uno_ext_getMapping(
363 uno_Mapping ** ppMapping, uno_Environment *pFrom, uno_Environment *pTo )
364 SAL_THROW_EXTERN_C()
366 OSL_ASSERT( 0 != ppMapping && 0 != pFrom && 0 != pTo );
367 if (0 != *ppMapping)
369 (*(*ppMapping)->release)( *ppMapping );
370 *ppMapping = 0;
373 /* FIXME check that mono's and sal's types have matching sizes
374 * like jni_bridge does? */
376 OUString const & from_env_typename = OUString::unacquired( &pFrom->pTypeName );
377 OUString const & to_env_typename = OUString::unacquired( &pTo->pTypeName );
379 uno_Mapping * mapping = 0;
383 if (from_env_typename.equalsAsciiL(
384 RTL_CONSTASCII_STRINGPARAM( UNO_LB_CLI )) &&
385 to_env_typename.equalsAsciiL(
386 RTL_CONSTASCII_STRINGPARAM( UNO_LB_UNO)))
388 Bridge * bridge =
389 new Bridge( pFrom, pTo->pExtEnv, true ); // ref count = 1
390 mapping = &bridge->m_mono2uno;
391 uno_registerMapping(
392 &mapping, Bridge_free, pFrom,
393 (uno_Environment *)pTo->pExtEnv, 0);
395 else if (from_env_typename.equalsAsciiL(
396 RTL_CONSTASCII_STRINGPARAM( UNO_LB_UNO)) &&
397 to_env_typename.equalsAsciiL(
398 RTL_CONSTASCII_STRINGPARAM( UNO_LB_CLI)))
400 Bridge * bridge =
401 new Bridge( pTo, pFrom->pExtEnv, false ); // ref count = 1
402 mapping = &bridge->m_uno2mono;
403 uno_registerMapping(
404 &mapping, Bridge_free,
405 (uno_Environment *)pFrom->pExtEnv, pTo, 0);
408 catch (BridgeRuntimeError & err)
410 #if OSL_DEBUG_LEVEL >= 1
411 OString cstr_msg(
412 OUStringToOString(
413 OUSTR("[mono_uno bridge error] ") + err.m_message,
414 RTL_TEXTENCODING_ASCII_US ) );
415 OSL_ENSURE( 0, cstr_msg.getStr() );
416 #endif
419 *ppMapping = mapping;
422 sal_Bool SAL_CALL component_canUnload( TimeValue * pTime )
423 SAL_THROW_EXTERN_C()
425 return (*g_moduleCount.canUnload)( &g_moduleCount, pTime );
428 } // extern "C"
430 MonoObject*
431 mono_uno::runtime_invoke (MonoMethod *method, void *obj, void **params,
432 MonoObject **exc, MonoDomain *domain)
434 mono_thread_attach( domain );
435 return mono_runtime_invoke( method, obj, params, exc );