Bump for 3.6-28
[LibreOffice.git] / cli_ure / source / mono_bridge / bridge.cs
blob6fdd78ebfd46a90e45f467aa92cc92847eb9ce2b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 namespace com.sun.star.bridges.mono_uno /* FIXME use some uno.foo namespace ? */
32 using System;
33 using System.Reflection;
34 using System.Runtime.InteropServices;
35 using System.Runtime.Remoting;
36 using System.Text;
37 using uno.Binary;
38 using uno.rtl;
39 using uno.Typelib;
41 public unsafe class Bridge
43 static IntPtr unoEnvironment;
44 static cli_uno.Cli_environment managedEnvironment;
46 Bridge(IntPtr unoEnv)
48 unoEnvironment = unoEnv;
49 managedEnvironment = new cli_uno.Cli_environment();
52 public unsafe IntPtr MapManagedToUno(object managedData, TypeDescription *td)
54 IntPtr result = new IntPtr(null);
56 // get oid from managed environment
57 string oid = cli_uno.Cli_environment.getObjectIdentifier(managedData);
59 UString* unoOid = null;
60 UString.NewFromString(&unoOid, oid);
61 uno.Binary.Environment.GetRegisteredInterface(unoEnvironment,
62 ref result,
63 unoOid,
64 (InterfaceTypeDescription *)td);
65 if (result == IntPtr.Zero)
66 lock (typeof(cli_uno.Cli_environment))
68 uno.Binary.Environment.GetRegisteredInterface(unoEnvironment,
69 ref result,
70 unoOid,
71 (InterfaceTypeDescription *)td);
72 if (result == IntPtr.Zero)
73 result = CreateManagedProxy(managedData, td, unoOid);
76 UString.Release(unoOid);
78 return result;
81 public unsafe object MapUnoToManaged(IntPtr unoInterface, InterfaceTypeDescription *iTD)
83 object result = null;
85 UString* oidPtr = null;
86 uno.Binary.Environment.GetObjectIdentifier(unoEnvironment, &oidPtr, unoInterface);
88 // See if the interface was already mapped
89 Type ifaceType = MapUnoType((TypeDescription *)iTD);
90 string oid = UString.UStringToString(oidPtr);
91 // the string is owned by unoEnvironment
92 oidPtr = null;
94 lock (managedEnvironment)
96 result = managedEnvironment.getRegisteredInterface(oid, ifaceType);
97 if (result != null)
99 // There is already an registered object. It can either be a proxy
100 // for the UNO object or a real cli object. In the first case we
101 // tell the proxy that it shall also represent the current UNO
102 // interface. If it already does that, then it does nothing
103 if (RemotingServices.IsTransparentProxy(result))
105 UnoInterfaceProxy p = (UnoInterfaceProxy)RemotingServices.GetRealProxy(result);
106 p.AddUnoInterface(unoInterface, iTD);
109 else
111 result = UnoInterfaceProxy.Create(this, unoInterface, iTD, oid);
115 return result;
118 // FIXME convert cli types to expected types, e.g a long to a short where the uno type
119 // is a sal_Int16. This could be necessary if a scripting language (typeless) is used
120 // @param assign the uno_data has to be destructed (in/out args)
121 unsafe void MapToUno(void *unoData, object managedData,
122 // FIXME it's a TypeDescriptionReference
123 TypeDescription *type, bool assign)
125 // FIXME acquire the TypeDescription?
126 // FIXME assert that all the type equivalences in the comments hold
127 switch (type->eTypeClass)
129 case TypeClass.VOID:
130 break;
131 case TypeClass.CHAR:
132 *(ushort *)unoData = (char)managedData; // sal_Unicode = ushort
133 break;
134 case TypeClass.BOOLEAN:
135 *(byte *)unoData = (bool)managedData ? (byte)1 : (byte)0; // sal_Bool = byte
136 break;
137 case TypeClass.BYTE:
138 *(byte *)unoData = (byte)managedData; // sal_Int8 = byte
139 break;
140 case TypeClass.SHORT:
141 *(short *)unoData = (short)managedData; // sal_Int16 = short
142 break;
143 case TypeClass.UNSIGNED_SHORT:
144 *(ushort *)unoData = (ushort)managedData; // sal_uInt16 = ushort
145 break;
146 case TypeClass.LONG:
147 *(int *)unoData = (int)managedData; // sal_Int32 = int
148 break;
149 case TypeClass.UNSIGNED_LONG:
150 *(uint *)unoData = (uint)managedData; // sal_uInt32 = uint
151 break;
152 case TypeClass.HYPER:
153 *(long *)unoData = (long)managedData; // sal_Int64 = long
154 break;
155 case TypeClass.UNSIGNED_HYPER:
156 *(ulong *)unoData = (ulong)managedData; // sal_uInt64 = ulong
157 break;
158 case TypeClass.FLOAT:
159 *(float *)unoData = (float)managedData; // C++ float = C# float
160 break;
161 case TypeClass.DOUBLE:
162 *(double *)unoData = (double)managedData; // C++ double = C# double
163 break;
164 case TypeClass.STRING:
166 if (assign && *(UString **)unoData != null)
167 UString.Release(*(UString **)unoData);
169 *(UString **)unoData = null;
170 if (managedData == null)
172 UString.New((UString **)unoData);
174 else
176 string s = (string)managedData;
177 UString.NewFromString((UString **)unoData, s);
180 break;
181 case TypeClass.TYPE:
182 if (assign)
183 TypeDescriptionReference.Release(*(TypeDescriptionReference **)unoData);
185 *(TypeDescriptionReference **)unoData = MapManagedType((Type)managedData);
186 break;
187 case TypeClass.ANY:
189 uno.Binary.Any *binAny = (uno.Binary.Any *)unoData;
191 if (assign)
192 uno.Binary.Any.Destroy(binAny, null);
194 if (managedData == null)
196 uno.Binary.Any.Construct(binAny, null, null, null);
197 break;
200 uno.Any any = (uno.Any)managedData;
201 TypeDescription *valueTD = (TypeDescription *)MapManagedType(any.Type);
203 // if there's enough room in void *pReserved, store the value in the pointer
204 binAny->pData = &binAny->pReserved; // this triggers a bug in mcs < 1.1.4
205 switch (valueTD->eTypeClass)
207 case TypeClass.VOID:
208 break;
209 case TypeClass.CHAR:
210 *(ushort *)binAny->pData = (char)any.Value;
211 break;
212 case TypeClass.BOOLEAN:
213 *(byte *)binAny->pData = (bool)any.Value ? (byte)1 : (byte)0;
214 break;
215 case TypeClass.BYTE:
216 *(byte *)binAny->pData = (byte)any.Value;
217 break;
218 case TypeClass.SHORT:
219 *(short *)binAny->pData = (short)any.Value;
220 break;
221 case TypeClass.UNSIGNED_SHORT:
222 *(ushort *)binAny->pData = (ushort)any.Value;
223 break;
224 case TypeClass.LONG:
225 *(int *)binAny->pData = (int)any.Value;
226 break;
227 case TypeClass.UNSIGNED_LONG:
228 *(uint *)binAny->pData = (uint)any.Value;
229 break;
230 case TypeClass.HYPER:
231 if (sizeof(long) > sizeof(void *))
232 binAny->pData = uno.rtl.Mem.Allocate(sizeof(long));
234 *(long *)binAny->pData = (long)any.Value;
235 break;
236 case TypeClass.UNSIGNED_HYPER:
237 if (sizeof(ulong) > sizeof(void *))
238 binAny->pData = uno.rtl.Mem.Allocate(sizeof(ulong));
240 *(ulong *)binAny->pData = (ulong)any.Value;
241 break;
242 case TypeClass.FLOAT:
243 if (sizeof(float) > sizeof(void *)) // FIXME can this happen?
244 binAny->pData = uno.rtl.Mem.Allocate(sizeof(float));
246 *(float *)binAny->pData = (float)any.Value;
247 break;
248 case TypeClass.DOUBLE:
249 if (sizeof(double) > sizeof(void *))
250 binAny->pData = uno.rtl.Mem.Allocate(sizeof(double));
252 *(double *)binAny->pData = (double)any.Value;
253 break;
254 case TypeClass.STRING:
255 // string anies are used so often, that we handle them
256 // separately, to be a little faster than with an
257 // extra MapToUno call
259 // the Any was already destroyed, can't contain a
260 // valid string that we could leak here.
261 *(UString **)binAny->pData = null;
263 if (managedData == null)
265 UString.New((UString **)binAny->pData);
267 else
269 string s = (string)any.Value;
270 UString.NewFromString((UString **)binAny->pData, s);
272 // the string is owned by the Any
273 break;
274 case TypeClass.ENUM:
275 *(int *) binAny->pData = System.Convert.ToInt32(any.Value);
276 break;
277 case TypeClass.TYPE:
278 case TypeClass.SEQUENCE:
279 case TypeClass.INTERFACE:
280 binAny->pReserved = null;
281 MapToUno(binAny->pData, any.Value, valueTD, false /* no assign */);
282 break;
283 case TypeClass.STRUCT:
284 case TypeClass.EXCEPTION:
285 binAny->pData = uno.rtl.Mem.Allocate(valueTD->nSize);
286 MapToUno(binAny->pData, any.Value, valueTD, false /* no assign */);
287 break;
288 default:
289 // FIXME
290 throw new Exception();
292 binAny->pType = (TypeDescriptionReference *)valueTD;
293 TypeDescriptionReference.Acquire(binAny->pType);
295 break;
296 case TypeClass.ENUM:
297 *(int *)unoData = System.Convert.ToInt32(managedData);
298 break;
299 case TypeClass.STRUCT:
300 case TypeClass.EXCEPTION:
302 TypeDescription *td = null; // FIXME leak
303 TypeDescriptionReference.GetDescription(&td, (TypeDescriptionReference *)type);
304 CompoundTypeDescription *compTD = (CompoundTypeDescription *)td;
305 StructTypeDescription *structTD = null;
307 if (type->eTypeClass == TypeClass.STRUCT)
308 structTD = (StructTypeDescription *)type;
310 if (((TypeDescription *)compTD)->bComplete == 0)
311 TypeDescription.Complete((TypeDescription **)&compTD);
313 int members = compTD->nMembers;
314 Type managedType = null;
315 if (managedData != null)
316 managedType = managedData.GetType();
318 if (compTD->pBaseTypeDescription != null)
319 MapToUno(unoData, managedData,
320 (TypeDescription *)((TypeDescription *)compTD->pBaseTypeDescription)->pWeakRef,
321 assign);
323 TypeDescriptionReference *memberType = null;
324 for (int i = 0; i < members; ++i)
326 memberType = compTD->ppTypeRefs[i];
328 object val = null;
329 if (managedData != null)
331 string fieldName = UString.UStringToString(compTD->ppMemberNames[i]);
332 FieldInfo fieldInfo = managedType.GetField(fieldName);
333 // special case for Exception.Message property
334 // The com.sun.star.uno.Exception.Message field is mapped to the
335 // System.Exception property. Type.GetField("Message") returns null
336 if (fieldInfo == null &&
337 UString.UStringToString(type->pTypeName) == "com.sun.star.uno.Exception")
339 // get ExceptionMessage property
340 if (fieldName == "Message")
342 PropertyInfo propInfo = managedType.GetProperty(fieldName);
343 val = propInfo.GetValue(managedData, null);
344 } // FIXME else throw exception
346 else if (fieldInfo != null)
348 val = fieldInfo.GetValue(managedData);
349 } // FIXME else throw exception
352 void *p = (byte *)unoData + compTD->pMemberOffsets[i];
353 // When using polymorphic structs then the parameterized members can be null.
354 // Then we set a default value.
355 bool useDefault = ((structTD != null &&
356 structTD->pParameterizedTypes != null &&
357 structTD->pParameterizedTypes[i] == 1 &&
358 val == null) ||
359 managedData == null);
360 switch (memberType->eTypeClass)
362 case TypeClass.CHAR:
363 if (useDefault)
364 *(ushort *)p = 0;
365 else
366 *(ushort *)p = (char)val;
367 break;
368 case TypeClass.BOOLEAN:
369 if (useDefault)
370 *(byte *)p = (byte)0;
371 else
372 *(byte *)p = (bool)val ? (byte)1 : (byte)0;
373 break;
374 case TypeClass.BYTE:
375 if (useDefault)
376 *(byte *)p = (byte)0;
377 else
378 *(byte *)p = (byte)val;
379 break;
380 case TypeClass.SHORT:
381 if (useDefault)
382 *(short *)p = (short)0;
383 else
384 *(short *)p = (short)val;
385 break;
386 case TypeClass.UNSIGNED_SHORT:
387 if (useDefault)
388 *(ushort *)p = (ushort)0;
389 else
390 *(ushort *)p = (ushort)val;
391 break;
392 case TypeClass.LONG:
393 if (useDefault)
394 *(int *)p = 0;
395 else
396 *(int *)p = (int)val;
397 break;
398 case TypeClass.UNSIGNED_LONG:
399 if (useDefault)
400 *(uint *)p = (uint)0;
401 else
402 *(uint *)p = (uint)val;
403 break;
404 case TypeClass.HYPER:
405 if (useDefault)
406 *(long *)p = (long)0;
407 else
408 *(long *)p = (long)val;
409 break;
410 case TypeClass.UNSIGNED_HYPER:
411 if (useDefault)
412 *(ulong *)p = (ulong)0;
413 else
414 *(ulong *)p = (ulong)val;
415 break;
416 case TypeClass.FLOAT:
417 if (useDefault)
418 *(float *)p = 0.0F;
419 else
420 *(float *)p = (float)val;
421 break;
422 case TypeClass.DOUBLE:
423 if (useDefault)
424 *(double *)p = 0.0;
425 else
426 *(double *)p = (double)val;
427 break;
428 default:
429 // FIXME enum should be converted here
430 MapToUno(p, val, (TypeDescription *)memberType, assign);
431 break;
434 // FIXME exception handling
436 break;
437 case TypeClass.SEQUENCE:
439 TypeDescription *td = null; // FIXME
440 TypeDescriptionReference.GetDescription(&td, (TypeDescriptionReference *)type);
441 TypeDescriptionReference *elementType =
442 ((IndirectTypeDescription *)td)->pType;
444 SequencePtr seq = new SequencePtr();
446 if (managedData != null)
448 Array array = (Array)managedData;
449 int length = array.GetLength(0);
451 switch (elementType->eTypeClass)
453 case TypeClass.CHAR:
454 seq = SequencePtr.Allocate(length, sizeof(ushort));
455 Marshal.Copy((char [])managedData, 0, seq.elementsPtr, length);
456 break;
457 /* case TypeClass.BOOLEAN:
458 // FIXME bool vs. byte ???
459 seq = SequencePtr.Allocate(length, sizeof(byte));
460 Marshal.Copy((byte [])managedData, 0, seq.elementsPtr, length);
461 break;*/
462 case TypeClass.BYTE:
463 seq = SequencePtr.Allocate(length, sizeof(byte));
464 Marshal.Copy((byte [])managedData, 0, seq.elementsPtr, length);
465 break;
466 case TypeClass.SHORT:
467 seq = SequencePtr.Allocate(length, sizeof(short));
468 Marshal.Copy((short [])managedData, 0, seq.elementsPtr, length);
469 break;
470 /* case TypeClass.UNSIGNED_SHORT:
471 seq = SequencePtr.Allocate(length, sizeof(ushort));
472 Marshal.Copy((short [])managedData, 0, seq.elementsPtr, length);
473 break; */
474 case TypeClass.LONG:
475 seq = SequencePtr.Allocate(length, sizeof(int));
476 Marshal.Copy((int [])managedData, 0, seq.elementsPtr, length);
477 break;
478 /* case TypeClass.UNSIGNED_LONG:
479 seq = SequencePtr.Allocate(length, sizeof(uint));
480 Marshal.Copy((int [])managedData, 0, seq.elementsPtr, length);
481 break; */
482 case TypeClass.HYPER:
483 seq = SequencePtr.Allocate(length, sizeof(long));
484 Marshal.Copy((long [])managedData, 0, seq.elementsPtr, length);
485 break;
486 /* case TypeClass.UNSIGNED_HYPER:
487 seq = SequencePtr.Allocate(length, sizeof(ulong));
488 Marshal.Copy((long [])managedData, 0, seq.elementsPtr, length);
489 break; */
490 case TypeClass.FLOAT:
491 seq = SequencePtr.Allocate(length, sizeof(float));
492 Marshal.Copy((float [])managedData, 0, seq.elementsPtr, length);
493 break;
494 case TypeClass.DOUBLE:
495 seq = SequencePtr.Allocate(length, sizeof(double));
496 Marshal.Copy((double [])managedData, 0, seq.elementsPtr, length);
497 break;
498 case TypeClass.STRING:
500 seq = SequencePtr.Allocate(length, sizeof(void *));
501 string[] stringArray = (string [])managedData;
502 for (int i = 0; i < length; ++i)
504 UString** pStr = ((UString** )seq.elementsPtr) + i;
505 *pStr = null;
506 UString.NewFromString(pStr, stringArray[i]);
507 // string ownership goes to callee
510 break;
511 case TypeClass.ENUM:
512 seq = SequencePtr.Allocate(length, sizeof(int));
513 for (int i = 0; i < length; ++i)
514 ((int *)seq.elementsPtr)[i] =
515 Convert.ToInt32(array.GetValue(i));
516 break;
517 case TypeClass.TYPE:
518 case TypeClass.ANY:
519 case TypeClass.STRUCT:
520 case TypeClass.EXCEPTION:
521 case TypeClass.SEQUENCE:
522 case TypeClass.INTERFACE:
523 // FIXME: surely we can do better for this lot [!] - sign problems ...
524 case TypeClass.BOOLEAN:
525 case TypeClass.UNSIGNED_SHORT:
526 case TypeClass.UNSIGNED_LONG:
527 case TypeClass.UNSIGNED_HYPER:
529 seq = SequencePtr.Allocate(
530 length, ((TypeDescription *)elementType)->nSize);
532 for (int i = 0; i < length; ++i)
534 void *p =
535 (byte *)seq.elementsPtr +
536 i * ((TypeDescription *)elementType)->nSize;
537 object elementData = ((Array)managedData).GetValue(i);
538 MapToUno(p, elementData,
539 (TypeDescription *)((TypeDescription *)elementType)->pWeakRef,
540 false /* no assign */);
542 // FIXME exception handling
544 break;
545 default:
546 break; // FIXME throw some exception
549 else
551 seq = SequencePtr.Allocate(0, sizeof(int));
553 *(SequencePtr *)unoData = seq;
555 break;
556 case TypeClass.INTERFACE:
558 if (assign && *(void **)unoData != null)
559 uno.Binary.Interface.Release(new IntPtr(*(void **)unoData));
561 if (managedData == null)
562 *(void **)unoData = null;
563 else
565 TypeDescription *td = null; // FIXME leak
566 TypeDescriptionReference.GetDescription(&td, (TypeDescriptionReference *)type);
567 *(void **)unoData = MapManagedToUno(managedData, td).ToPointer();
569 break;
571 default:
572 // FIXME throw some exception
573 break;
577 unsafe void MapToManaged(ref object managedData, void *unoData,
578 TypeDescriptionReference *type, Type info, bool dontCreateObj)
580 switch (type->eTypeClass)
582 case TypeClass.CHAR:
583 managedData = (char)*(ushort *)unoData;
584 break;
585 case TypeClass.BOOLEAN:
586 managedData = (*(byte *)unoData != 0);
587 break;
588 case TypeClass.BYTE:
589 managedData = *(byte *)unoData;
590 break;
591 case TypeClass.SHORT:
592 managedData = *(short *)unoData;
593 break;
594 case TypeClass.UNSIGNED_SHORT:
595 managedData = *(ushort *)unoData;
596 break;
597 case TypeClass.LONG:
598 managedData = *(int *)unoData;
599 break;
600 case TypeClass.UNSIGNED_LONG:
601 managedData = *(uint *)unoData;
602 break;
603 case TypeClass.HYPER:
604 managedData = *(long *)unoData;
605 break;
606 case TypeClass.UNSIGNED_HYPER:
607 managedData = *(ulong *)unoData;
608 break;
609 case TypeClass.FLOAT:
610 managedData = *(float *)unoData;
611 break;
612 case TypeClass.DOUBLE:
613 managedData = *(double *)unoData;
614 break;
615 case TypeClass.STRING:
616 managedData = UString.UStringToString(*(UString **)unoData);
617 break;
618 case TypeClass.TYPE:
619 managedData = MapUnoType(*(TypeDescriptionReference **)unoData);
620 break;
621 case TypeClass.ANY:
623 uno.Binary.Any *binAny = (uno.Binary.Any *)unoData;
624 if (binAny->pType->eTypeClass != TypeClass.VOID)
626 object value = null;
627 MapToManaged(ref value, binAny->pData, binAny->pType, null, false);
628 managedData = new uno.Any(MapUnoType(binAny->pType), value);
630 else
632 managedData = uno.Any.VOID;
634 break;
636 case TypeClass.ENUM:
637 if (info != null)
638 managedData = Enum.ToObject(
639 info.GetElementType(), *(int *)unoData);
640 else
641 managedData = Enum.ToObject(
642 MapUnoType(type), *(int *)unoData);
643 break;
644 case TypeClass.STRUCT:
645 case TypeClass.EXCEPTION:
647 TypeDescription *td = null; // FIXME leak
648 TypeDescriptionReference.GetDescription(&td, (TypeDescriptionReference *)type);
649 CompoundTypeDescription *compTD = (CompoundTypeDescription *)td;
651 if (((TypeDescription *)compTD)->bComplete == 0)
652 TypeDescription.Complete((TypeDescription **)&compTD);
654 // create the type
655 Type managedType = LoadCliType(td->pTypeName);
657 // detect if we recursivly convert inherited
658 // structures. If this point is reached because of a
659 // recursive call during converting a struct then we must
660 // not create a new object rather we use the one in
661 // cli_data argument.
662 object managedObject;
663 if (dontCreateObj)
664 managedObject = managedData;
665 else
667 // Special handling for Exception conversion. We must
668 // call constructor System::Exception to pass the
669 // message string
670 if (typeof(unoidl.com.sun.star.uno.Exception).IsAssignableFrom(managedType))
672 // We need to get the Message field. Therefore we
673 // must obtain the offset from the
674 // typedescription. The base interface of all
675 // exceptions is com::sun::star::uno::Exception
676 // which contains the message
677 CompoundTypeDescription *pCTD = compTD;
678 while (pCTD->pBaseTypeDescription != null)
679 pCTD = pCTD->pBaseTypeDescription;
681 int pos = -1;
682 for (int i = 0; i < pCTD->nMembers; ++i)
684 if (UString.UStringToString(pCTD->ppMemberNames[i]) == "Message")
686 pos = i;
687 break;
691 int offset = pCTD->pMemberOffsets[pos];
692 // With the offset within the exception we can get
693 // the message string
694 string message = UString.UStringToString(
695 (*(UString **)((byte *)unoData + offset)));
696 // We need to find a constructor for the exception
697 // that takes the message string. We assume that
698 // the first argument is the message string
699 ConstructorInfo[] ctorInfos = managedType.GetConstructors();
700 ConstructorInfo ctorInfo = null;
701 // Constructor must at least have 2 params for the base
702 // unoidl.com.sun.star.uno.Exception (String, Object);
703 int numArgs = -1;
704 foreach (ConstructorInfo ci in ctorInfos)
706 numArgs = ci.GetParameters().Length;
707 if (numArgs < 2)
708 continue;
709 ctorInfo = ci;
710 break;
713 // Prepare parameters for constructor
714 object[] args = new object[numArgs];
715 // only initialize the first argument with the
716 // message. All unoidl.<Foo Exception>s are
717 // autogenerated, we know that this is safe.
718 args[0] = message;
719 managedObject = ctorInfo.Invoke(args);
721 else
722 managedObject = Activator.CreateInstance(managedType);
725 TypeDescriptionReference **memberTypeRefs = compTD->ppTypeRefs;
726 int *memberOffsets = compTD->pMemberOffsets;
728 if (compTD->pBaseTypeDescription != null)
730 // convert inherited struct
731 // cliObj is passed inout (args in_param, out_param are true), hence the passed
732 // cliObj is used by the callee instead of a newly created struct
733 MapToManaged(ref managedObject, unoData,
734 ((TypeDescription *)compTD->pBaseTypeDescription)->pWeakRef,
735 null,
736 true);
738 for (int i = compTD->nMembers - 1; i >= 0; --i)
740 TypeDescriptionReference *memberType = memberTypeRefs[i];
741 string memberName = UString.UStringToString(compTD->ppMemberNames[i]);
742 FieldInfo fieldInfo = managedType.GetField(memberName);
743 // special case for Exception.Message. The field has already been
744 // set while constructing cli object
745 if (fieldInfo == null &&
746 UString.UStringToString(type->pTypeName) == "com.sun.star.uno.Exception")
747 continue;
749 void *p = (byte *)unoData + memberOffsets[i];
750 switch (memberType->eTypeClass)
752 case TypeClass.CHAR:
753 fieldInfo.SetValue(managedObject, (char)*(short *)p);
754 break;
755 case TypeClass.BOOLEAN:
756 fieldInfo.SetValue(managedObject, (*(byte *)p) != 0);
757 break;
758 case TypeClass.BYTE:
759 fieldInfo.SetValue(managedObject, *(byte *)p);
760 break;
761 case TypeClass.SHORT:
762 fieldInfo.SetValue(managedObject, *(short *)p);
763 break;
764 case TypeClass.UNSIGNED_SHORT:
765 fieldInfo.SetValue(managedObject, *(ushort *)p);
766 break;
767 case TypeClass.LONG:
768 fieldInfo.SetValue(managedObject, *(int *)p);
769 break;
770 case TypeClass.UNSIGNED_LONG:
771 fieldInfo.SetValue(managedObject, *(uint *)p);
772 break;
773 case TypeClass.HYPER:
774 fieldInfo.SetValue(managedObject, *(long *)p);
775 break;
776 case TypeClass.UNSIGNED_HYPER:
777 fieldInfo.SetValue(managedObject, *(ulong *)p);
778 break;
779 case TypeClass.FLOAT:
780 fieldInfo.SetValue(managedObject, *(float *)p);
781 break;
782 case TypeClass.DOUBLE:
783 fieldInfo.SetValue(managedObject, *(double *)p);
784 break;
785 default:
787 object managedValue = null;
788 MapToManaged(ref managedValue, p, memberType, null, false);
789 fieldInfo.SetValue(managedObject, managedValue);
790 break;
794 managedData = managedObject;
795 break;
797 case TypeClass.SEQUENCE:
799 SequencePtr seq = *(SequencePtr *)unoData;
800 int length = seq.nElements;
802 TypeDescription *td = null; // FIXME leak
803 TypeDescriptionReference.GetDescription(&td, (TypeDescriptionReference *)type);
804 TypeDescriptionReference *elementType = ((IndirectTypeDescription *)td)->pType;
806 switch (elementType->eTypeClass)
808 case TypeClass.CHAR:
810 char[] array = new char[length];
811 Marshal.Copy(seq.elementsPtr, array, 0, length);
812 managedData = array;
813 break;
815 case TypeClass.BOOLEAN:
817 bool[] array = new bool[length];
818 byte *source = (byte *)seq.elementsPtr;
819 if (length > 0) fixed (bool *arrayPtr = array)
821 bool *dest = arrayPtr;
822 for (int i = 0; i < length; ++i)
823 *dest++ = (*source++ != 0);
825 managedData = array;
826 break;
828 case TypeClass.BYTE:
830 byte[] array = new byte[length];
831 byte *source = (byte *)seq.elementsPtr;
832 if (length > 0) fixed (byte *arrayPtr = array)
834 byte *dest = arrayPtr;
835 for (int i = 0; i < length; ++i)
836 *dest++ = *source++;
838 managedData = array;
839 break;
841 case TypeClass.SHORT:
843 short[] array = new short[length];
844 Marshal.Copy(seq.elementsPtr, array, 0, length);
845 managedData = array;
846 break;
848 case TypeClass.UNSIGNED_SHORT:
850 ushort[] array = new ushort[length];
851 ushort *source = (ushort *)seq.elementsPtr;
852 if (length > 0) fixed (ushort *arrayPtr = array)
854 ushort *dest = arrayPtr;
855 for (int i = 0; i < length; ++i)
856 *dest++ = *source++;
858 managedData = array;
859 break;
861 case TypeClass.LONG:
863 int[] array = new int[length];
864 Marshal.Copy(seq.elementsPtr, array, 0, length);
865 managedData = array;
866 break;
868 case TypeClass.UNSIGNED_LONG:
870 uint[] array = new uint[length];
871 uint *source = (uint *)seq.elementsPtr;
872 if (length > 0) fixed (uint *arrayPtr = array)
874 uint *dest = arrayPtr;
875 for (int i = 0; i < length; ++i)
876 *dest++ = *source++;
878 managedData = array;
879 break;
881 case TypeClass.HYPER:
883 long[] array = new long[length];
884 Marshal.Copy(seq.elementsPtr, array, 0, length);
885 managedData = array;
886 break;
888 case TypeClass.UNSIGNED_HYPER:
890 ulong[] array = new ulong[length];
891 ulong *source = (ulong *)seq.elementsPtr;
892 if (length > 0) fixed (ulong *arrayPtr = array)
894 ulong *dest = arrayPtr;
895 for (int i = 0; i < length; ++i)
896 *dest++ = *source++;
898 managedData = array;
899 break;
901 case TypeClass.FLOAT:
903 float[] array = new float[length];
904 Marshal.Copy(seq.elementsPtr, array, 0, length);
905 managedData = array;
906 break;
908 case TypeClass.DOUBLE:
910 double[] array = new double[length];
911 Marshal.Copy(seq.elementsPtr, array, 0, length);
912 managedData = array;
913 break;
915 case TypeClass.STRING:
917 string[] array = new string[length];
918 for (int i = 0; i < length; ++i)
920 UString *us = ((UString **)seq.elementsPtr)[i];
921 array[i] = UString.UStringToString(us);
923 managedData = array;
924 break;
926 case TypeClass.TYPE:
928 Type[] array = new Type[length];
929 for (int i = 0; i < length; ++i)
930 array[i] = MapUnoType(((TypeDescriptionReference **)
931 seq.elementsPtr)[i]);
932 managedData = array;
933 break;
935 case TypeClass.ANY:
937 uno.Any[] array = new uno.Any[length];
938 uno.Binary.Any *binAny = (uno.Binary.Any *)seq.elementsPtr;
939 for (int i = 0; i < length; ++i)
941 object any = new uno.Any();
942 MapToManaged(ref any, (void **)(binAny + i),
943 (TypeDescriptionReference *)elementType,
944 null, false);
945 array[i] = (uno.Any)any;
947 managedData = array;
948 break;
950 case TypeClass.ENUM:
952 Type enumType = null;
953 if (info != null)
955 enumType = info.GetElementType();
956 // enumType is EnumType[], get EnumType
957 enumType = enumType.GetElementType();
959 else
960 enumType = MapUnoType(elementType);
962 Array array = Array.CreateInstance(enumType, length);
963 for (int i = 0; i < length; ++i)
965 array.SetValue(Enum.ToObject(enumType,
966 ((int *)seq.elementsPtr)[i]),
969 managedData = array;
970 break;
972 case TypeClass.STRUCT:
973 case TypeClass.EXCEPTION:
975 Array array = Array.CreateInstance(MapUnoType(elementType), length);
976 if (length > 0)
978 // FIXME check this
979 byte *p = (byte *)seq.elementsPtr;
980 int size = ((TypeDescription *)elementType)->nSize;
981 for (int i = 0; i < length; ++i)
983 object val = null;
984 MapToManaged(ref val, p + (size * i), elementType, null, false);
985 array.SetValue(val, i);
988 managedData = array;
989 break;
991 // FIXME verify (says cli_data.cxx)
992 case TypeClass.SEQUENCE:
994 Array array = Array.CreateInstance(
995 MapUnoType(elementType), length);
996 if (length > 0)
998 SequencePtr *elements = (SequencePtr *)seq.elementsPtr;
999 for (int i = 0; i < length; ++i)
1001 object val = null;
1002 MapToManaged(ref val, elements + i, elementType, null, false);
1003 array.SetValue(val, i);
1006 managedData = array;
1007 break;
1009 case TypeClass.INTERFACE:
1011 Type ifaceType = MapUnoType(elementType);
1012 Array array = Array.CreateInstance(ifaceType, length);
1014 byte *p = (byte *)seq.elementsPtr;
1015 int size = ((TypeDescription *)elementType)->nSize;
1016 for (int i = 0; i < length; ++i)
1018 object val = null;
1019 MapToManaged(ref val, p + (size * i), elementType, null, false);
1020 array.SetValue(val, i);
1022 managedData = array;
1023 break;
1025 default:
1027 // FIXME throw some exception
1028 break;
1031 break;
1033 case TypeClass.INTERFACE:
1035 IntPtr unoI = new IntPtr(*(void **)unoData);
1036 if (unoI != IntPtr.Zero)
1038 TypeDescription *td = null; // FIXME leak
1039 TypeDescriptionReference.GetDescription(&td, type);
1040 managedData = MapUnoToManaged(unoI, (InterfaceTypeDescription *)td);
1042 else
1043 managedData = null;
1044 break;
1046 default:
1048 // FIXME throw some exception
1049 break;
1054 public static Type MapUnoType(TypeDescription *TD)
1056 return MapUnoType(TD->pWeakRef);
1059 public static Type MapUnoType(TypeDescriptionReference *TD)
1061 Type result;
1063 switch(TD->eTypeClass)
1065 case TypeClass.VOID:
1066 result = typeof(void);
1067 break;
1068 case TypeClass.CHAR:
1069 result = typeof(char);
1070 break;
1071 case TypeClass.BOOLEAN:
1072 result = typeof(bool);
1073 break;
1074 case TypeClass.BYTE:
1075 result = typeof(byte);
1076 break;
1077 case TypeClass.SHORT:
1078 result = typeof(short);
1079 break;
1080 case TypeClass.UNSIGNED_SHORT:
1081 result = typeof(ushort);
1082 break;
1083 case TypeClass.LONG:
1084 result = typeof(int);
1085 break;
1086 case TypeClass.UNSIGNED_LONG:
1087 result = typeof(uint);
1088 break;
1089 case TypeClass.HYPER:
1090 result = typeof(long);
1091 break;
1092 case TypeClass.UNSIGNED_HYPER:
1093 result = typeof(ulong);
1094 break;
1095 case TypeClass.FLOAT:
1096 result = typeof(float);
1097 break;
1098 case TypeClass.DOUBLE:
1099 result = typeof(double);
1100 break;
1101 case TypeClass.STRING:
1102 result = typeof(string);
1103 break;
1104 case TypeClass.TYPE:
1105 result = typeof(Type);
1106 break;
1107 case TypeClass.ANY:
1108 result = typeof(uno.Any);
1109 break;
1110 case TypeClass.ENUM:
1111 case TypeClass.STRUCT:
1112 case TypeClass.EXCEPTION:
1113 result = LoadCliType(TD->pTypeName);
1114 break;
1115 case TypeClass.INTERFACE:
1116 // special handling for XInterface, since it does not exist in cli.
1117 if (UString.UStringToString(TD->pTypeName) == "com.sun.star.uno.XInterface")
1118 result = typeof(object);
1119 else
1120 result = LoadCliType(TD->pTypeName);
1121 break;
1122 case TypeClass.SEQUENCE:
1124 TypeDescription *seqType = null; // FIXME leak
1125 TypeDescriptionReference.GetDescription(&seqType, TD);
1127 // FIXME do something with TD here?
1128 TypeDescriptionReference *elementTDRef =
1129 ((IndirectTypeDescription *)seqType)->pType;
1131 switch (elementTDRef->eTypeClass)
1133 case TypeClass.CHAR:
1134 result = Type.GetType("System.Char[]");
1135 break;
1136 case TypeClass.BOOLEAN:
1137 result = Type.GetType("System.Boolean[]");
1138 break;
1139 case TypeClass.BYTE:
1140 result = Type.GetType("System.Byte[]");
1141 break;
1142 case TypeClass.SHORT:
1143 result = Type.GetType("System.Int16[]");
1144 break;
1145 case TypeClass.UNSIGNED_SHORT:
1146 result = Type.GetType("System.UInt16[]");
1147 break;
1148 case TypeClass.LONG:
1149 result = Type.GetType("System.Int32[]");
1150 break;
1151 case TypeClass.UNSIGNED_LONG:
1152 result = Type.GetType("System.UInt32[]");
1153 break;
1154 case TypeClass.HYPER:
1155 result = Type.GetType("System.Int64[]");
1156 break;
1157 case TypeClass.UNSIGNED_HYPER:
1158 result = Type.GetType("System.UInt64[]");
1159 break;
1160 case TypeClass.FLOAT:
1161 result = Type.GetType("System.Single[]");
1162 break;
1163 case TypeClass.DOUBLE:
1164 result = Type.GetType("System.Double[]");
1165 break;
1166 case TypeClass.STRING:
1167 result = Type.GetType("System.String[]");
1168 break;
1169 case TypeClass.TYPE:
1170 result = Type.GetType("System.Type[]");
1171 break;
1172 case TypeClass.ANY:
1173 case TypeClass.ENUM:
1174 case TypeClass.EXCEPTION:
1175 case TypeClass.STRUCT:
1176 case TypeClass.INTERFACE:
1177 case TypeClass.SEQUENCE:
1178 result = LoadCliType(TD->pTypeName);
1179 break;
1180 default:
1181 // FIXME can't happen
1182 result = null;
1183 break;
1185 break;
1187 default:
1188 // FIXME can't happen
1189 result = null;
1190 break;
1192 return result;
1195 public static Type LoadCliType(UString* unoName)
1197 return LoadCliType(MapUnoTypeName(UString.UStringToString(unoName)));
1200 public static Type LoadCliType(string unoName)
1202 Type result = null;
1203 bool isPolymorphic = false;
1205 string loadName = unoName;
1206 int index = unoName.IndexOf('<');
1207 if (index != -1)
1209 loadName = unoName.Substring(0, index);
1210 isPolymorphic = true;
1213 result = Type.GetType(loadName + ",cli_uretypes");
1215 if (result == null)
1216 result = Type.GetType(loadName + ",cli_basetypes");
1218 if (result == null)
1219 result = Type.GetType(loadName, false);
1221 if (result == null)
1223 foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
1225 result = a.GetType(loadName, false);
1226 if (result != null)
1227 break;
1231 if (result == null)
1232 // FIXME don't use generic Exception type
1233 throw new Exception("A type could not be loaded: " + loadName);
1235 if (isPolymorphic)
1236 result = uno.PolymorphicType.GetType(result, unoName);
1238 return result;
1241 static TypeDescriptionReference *MapManagedType(Type managedType)
1243 TypeDescriptionReference *result = null;
1244 if (managedType == null)
1246 result = *TypeDescriptionReference.GetByTypeClass(TypeClass.VOID);
1247 TypeDescriptionReference.Acquire(result);
1248 return result;
1251 // check for Enum first,
1252 // because otherwise case System.TypeCode.Int32 applies
1253 if (managedType.IsEnum)
1255 UString* unoTypeName = MapManagedTypeName(managedType.FullName);
1256 TypeDescriptionReference.New(&result, TypeClass.ENUM, unoTypeName);
1257 TypeDescriptionReference.Acquire(result);
1259 else
1261 switch (System.Type.GetTypeCode(managedType))
1263 case System.TypeCode.Boolean:
1264 result = *TypeDescriptionReference.GetByTypeClass(TypeClass.BOOLEAN);
1265 TypeDescriptionReference.Acquire(result);
1266 break;
1267 case System.TypeCode.Char:
1268 result = *TypeDescriptionReference.GetByTypeClass(TypeClass.CHAR);
1269 TypeDescriptionReference.Acquire(result);
1270 break;
1271 case System.TypeCode.Byte:
1272 result = *TypeDescriptionReference.GetByTypeClass(TypeClass.BYTE);
1273 TypeDescriptionReference.Acquire(result);
1274 break;
1275 case System.TypeCode.Int16:
1276 result = *TypeDescriptionReference.GetByTypeClass(TypeClass.SHORT);
1277 TypeDescriptionReference.Acquire(result);
1278 break;
1279 case System.TypeCode.Int32:
1280 result = *TypeDescriptionReference.GetByTypeClass(TypeClass.LONG);
1281 TypeDescriptionReference.Acquire(result);
1282 break;
1283 case System.TypeCode.Int64:
1284 result = *TypeDescriptionReference.GetByTypeClass(TypeClass.HYPER);
1285 TypeDescriptionReference.Acquire(result);
1286 break;
1287 case System.TypeCode.UInt16:
1288 result = *TypeDescriptionReference.GetByTypeClass(TypeClass.UNSIGNED_SHORT);
1289 TypeDescriptionReference.Acquire(result);
1290 break;
1291 case System.TypeCode.UInt32:
1292 result = *TypeDescriptionReference.GetByTypeClass(TypeClass.UNSIGNED_LONG);
1293 TypeDescriptionReference.Acquire(result);
1294 break;
1295 case System.TypeCode.UInt64:
1296 result = *TypeDescriptionReference.GetByTypeClass(TypeClass.UNSIGNED_HYPER);
1297 TypeDescriptionReference.Acquire(result);
1298 break;
1299 case System.TypeCode.Single:
1300 result = *TypeDescriptionReference.GetByTypeClass(TypeClass.FLOAT);
1301 TypeDescriptionReference.Acquire(result);
1302 break;
1303 case System.TypeCode.Double:
1304 result = *TypeDescriptionReference.GetByTypeClass(TypeClass.DOUBLE);
1305 TypeDescriptionReference.Acquire(result);
1306 break;
1307 case System.TypeCode.String:
1308 result = *TypeDescriptionReference.GetByTypeClass(TypeClass.STRING);
1309 TypeDescriptionReference.Acquire(result);
1310 break;
1314 if (result == null)
1316 string managedTypeName = managedType.FullName;
1317 if (managedTypeName == "System.Void")
1319 result = *TypeDescriptionReference.GetByTypeClass(TypeClass.VOID);
1320 TypeDescriptionReference.Acquire(result);
1322 else if (managedTypeName == "System.Type")
1324 result = *TypeDescriptionReference.GetByTypeClass(TypeClass.TYPE);
1325 TypeDescriptionReference.Acquire(result);
1327 else if (managedTypeName == "uno.Any")
1329 result = *TypeDescriptionReference.GetByTypeClass(TypeClass.ANY);
1330 TypeDescriptionReference.Acquire(result);
1332 else
1334 UString* unoTypeName;
1336 uno.PolymorphicType poly = managedType as uno.PolymorphicType;
1337 if (poly != null)
1338 unoTypeName = MapManagedTypeName(poly.PolymorphicName);
1339 else
1340 unoTypeName = MapManagedTypeName(managedTypeName);
1342 TypeDescription *td = null;
1343 TypeDescription.GetByName(&td, unoTypeName);
1344 if (td != null)
1346 result = td->pWeakRef;
1347 TypeDescriptionReference.Acquire(result);
1348 TypeDescription.Release(td);
1353 if (result == null)
1355 // FIXME - quite probably we should throw an exception here instead.
1356 result = *TypeDescriptionReference.GetByTypeClass(TypeClass.VOID);
1357 TypeDescriptionReference.Acquire(result);
1360 return result;
1363 static string MapUnoTypeName(string typeName)
1365 StringBuilder buf = new StringBuilder();
1367 // determine if the type is a sequence and its dimensions
1368 int dims = 0;
1369 if (typeName[0] == '[')
1371 int index = 1;
1372 while (true)
1374 if (typeName[index++] == ']')
1375 ++dims;
1376 if (typeName[index++] != '[')
1377 break;
1379 typeName = typeName.Substring(index - 1);
1382 switch (typeName)
1384 case "boolean":
1385 buf.Append("System.Boolean");
1386 break;
1387 case "char":
1388 buf.Append("System.Char");
1389 break;
1390 case "byte":
1391 buf.Append("System.Byte");
1392 break;
1393 case "short":
1394 buf.Append("System.Int16");
1395 break;
1396 case "unsigned short":
1397 buf.Append("System.UInt16");
1398 break;
1399 case "long":
1400 buf.Append("System.Int32");
1401 break;
1402 case "unsigned long":
1403 buf.Append("System.UInt32");
1404 break;
1405 case "hyper":
1406 buf.Append("System.Int64");
1407 break;
1408 case "unsigned hyper":
1409 buf.Append("System.UInt64");
1410 break;
1411 case "float":
1412 buf.Append("System.Single");
1413 break;
1414 case "double":
1415 buf.Append("System.Double");
1416 break;
1417 case "string":
1418 buf.Append("System.String");
1419 break;
1420 case "void":
1421 buf.Append("System.Void");
1422 break;
1423 case "type":
1424 buf.Append("System.Type");
1425 break;
1426 case "com.sun.star.uno.XInterface":
1427 buf.Append("System.Object");
1428 break;
1429 case "any":
1430 buf.Append("uno.Any");
1431 break;
1432 default:
1433 // put "unoidl." at the beginning
1434 buf.Append("unoidl.");
1435 // for polymorphic struct types remove the brackets, e.g. mystruct<bool> -> mystruct
1436 buf.Append(MapUnoPolymorphicName(typeName));
1437 break;
1440 // append []
1441 for ( ; dims > 0; --dims)
1442 buf.Append("[]");
1444 return buf.ToString();
1447 /** For example, there is a uno type
1448 com.sun.star.Foo<char, long>.
1449 The values in the type list
1450 are uno types and are replaced by cli types, such as System.Char,
1451 System.Int32, etc.
1453 static string MapUnoPolymorphicName(string unoName)
1455 int startIndex = unoName.LastIndexOf('<');
1456 if (startIndex == -1)
1457 return unoName;
1459 // get the type list within < and >
1460 int endIndex = unoName.LastIndexOf('>');
1461 string list = unoName.Substring(startIndex + 1, endIndex - startIndex - 1);
1463 // parse the type list and replace the types with the corresponding CLI types
1464 char[] delimiters = new char[] { ',' };
1465 string[] unoTypes = list.Split(delimiters);
1467 StringBuilder builder = new StringBuilder(unoName.Substring(0, startIndex + 1));
1469 int typeCount = unoTypes.Length;
1470 for (int i = 0; i < typeCount; ++i)
1471 builder.Append(MapUnoTypeName(unoTypes[i]));
1473 builder.Append('>');
1474 return builder.ToString();
1477 static UString* MapManagedTypeName(string typeName)
1479 int dims = 0;
1480 int index = 0;
1482 if ((index = typeName.IndexOf("[]")) > 0)
1484 dims = 1;
1486 int curIndex = index;
1487 while ((curIndex + 2) < typeName.Length &&
1488 (curIndex = typeName.IndexOf("[]", curIndex + 2)) > 0)
1489 ++dims;
1491 // get the element name by removing the brackets
1492 typeName = typeName.Substring(0, index);
1495 StringBuilder buf = new StringBuilder(256);
1496 for (; dims > 0; --dims)
1497 buf.Append("[]");
1499 switch (typeName)
1501 case "System.Boolean":
1502 buf.Append("boolean");
1503 break;
1504 case "System.Char":
1505 buf.Append("char");
1506 break;
1507 case "System.Byte":
1508 buf.Append("byte");
1509 break;
1510 case "System.Int16":
1511 buf.Append("short");
1512 break;
1513 case "System.UInt16":
1514 buf.Append("unsigned short");
1515 break;
1516 case "System.Int32":
1517 buf.Append("long");
1518 break;
1519 case "System.UInt32":
1520 buf.Append("unsigned long");
1521 break;
1522 case "System.Int64":
1523 buf.Append("hyper");
1524 break;
1525 case "System.UInt64":
1526 buf.Append("unsigned hyper");
1527 break;
1528 case "System.Single":
1529 buf.Append("float");
1530 break;
1531 case "System.Double":
1532 buf.Append("double");
1533 break;
1534 case "System.String":
1535 buf.Append("string");
1536 break;
1537 case "System.Void":
1538 buf.Append("void");
1539 break;
1540 case "System.Type":
1541 buf.Append("type");
1542 break;
1543 case "System.Object":
1544 buf.Append("com.sun.star.uno.XInterface");
1545 break;
1546 case "uno.Any":
1547 buf.Append("any");
1548 break;
1549 default:
1551 string name = MapManagedPolymorphicName(typeName);
1552 int i = name.IndexOf('.');
1553 buf.Append(name.Substring(i + 1));
1554 break;
1558 UString *rtl_uString = null;
1559 UString.NewFromStringBuilder(&rtl_uString, buf);
1560 return rtl_uString;
1563 static string MapManagedPolymorphicName(string unoName)
1565 int startIndex = unoName.LastIndexOf('<');
1566 if (startIndex == -1)
1567 return unoName;
1569 // get the type list withing < and >
1570 int endIndex = unoName.LastIndexOf('>');
1571 string list = unoName.Substring(startIndex + 1, endIndex - startIndex - 1);
1573 // parse the type list and replace the types with the corresponding CLI types
1574 char[] delimiters = new char[] { ',' };
1575 string[] unoTypes = list.Split(delimiters);
1577 StringBuilder builder = new StringBuilder(unoName.Substring(0, startIndex + 1));
1579 int typeCount = unoTypes.Length;
1580 for (int i = 0; i < typeCount; ++i)
1581 builder.Append(UString.UStringToString(MapManagedTypeName(unoTypes[i])));
1582 builder.Append('>');
1583 return builder.ToString();
1586 [StructLayout(LayoutKind.Explicit)]
1587 private unsafe struct largest
1589 [FieldOffset(0)] long n;
1590 [FieldOffset(0)] double d;
1591 [FieldOffset(0)] void *p;
1592 [FieldOffset(0)] uno.Binary.Any a;
1595 // FIXME args[i] must be of same type as return value
1596 public unsafe uno.Any CallUno(IntPtr unoInterface, TypeDescription *memberTD,
1597 TypeDescriptionReference *returnType, int nParams,
1598 MethodParameter *parameters, object[] args,
1599 Type[] argTypes, out uno.Any exception)
1601 int returnSize = sizeof(largest);
1603 if (returnType != null &&
1604 (returnType->eTypeClass == TypeClass.STRUCT ||
1605 returnType->eTypeClass == TypeClass.EXCEPTION))
1607 // FIXME leak
1608 TypeDescription *td = null;
1609 TypeDescriptionReference.GetDescription(&td, returnType);
1611 if (td->nSize > returnSize)
1612 returnSize = td->nSize;
1615 // Prepare memory that contains all converted arguments and
1616 // return values. The memory block contains first pointers to
1617 // the arguments which are in the same block For example, 2
1618 // arguments, 1 ret.
1620 // | Pointer
1621 // | Pointer
1622 // | Return value
1623 // | Arg 1
1624 // | Arg 2
1626 // If an argument is larger then struct largest, such as some
1627 // structures, then the pointer points to an extra block of
1628 // memory. The same goes for a big return value.
1629 // FIXME the last sentence is bullshit. Get it deleted from cli_uno ;)
1630 byte *mem = stackalloc byte[nParams * sizeof(void *) +
1631 returnSize +
1632 nParams * sizeof(largest)];
1634 // array of pointers to args
1635 void **unoArgPtrs = (void **)mem;
1637 // Return Value
1638 void *unoRetPtr = null;
1639 largest *unoArgs = (largest *)(unoArgPtrs + nParams);
1640 if (memberTD->eTypeClass != TypeClass.INTERFACE_ATTRIBUTE || nParams != 1)
1642 // If an attribute is set, then unoRet must be null, e.g. void setAttribute(int)
1643 unoRetPtr = (void *)unoArgs;
1644 unoArgs = (largest *)((byte *)unoRetPtr + returnSize);
1647 for (int i = 0; i < nParams; ++i)
1649 TypeDescriptionReference *typeref = (TypeDescriptionReference *)parameters[i].pTypeRef;
1650 TypeDescription *type = null;
1651 TypeDescriptionReference.GetDescription(&type, typeref);
1652 unoArgPtrs[i] = unoArgs + i;
1653 if ((type->eTypeClass == TypeClass.STRUCT ||
1654 type->eTypeClass == TypeClass.EXCEPTION) &&
1655 (type->nSize > sizeof(largest)))
1657 // stackalloc is only allowed in initializers
1658 byte *bigArgPtr = stackalloc byte[type->nSize];
1660 unoArgPtrs[i] = bigArgPtr;
1663 if (parameters[i].bIn != 0)
1665 // FIXME error handling
1666 MapToUno(unoArgPtrs[i], args[i], (TypeDescription*)typeref, false /* no assign */);
1670 uno.Binary.Any unoExceptionHolder;
1671 uno.Binary.Any *unoExc = &unoExceptionHolder;
1673 // call binary uno
1674 uno.Binary.Interface.Dispatch(
1675 unoInterface, memberTD, unoRetPtr, unoArgPtrs, &unoExc);
1677 if (unoExc == null)
1679 exception = uno.Any.VOID;
1681 // convert out args, destroy uno args
1682 for (int i = 0; i < nParams; ++i)
1684 // FIXME it's a TypeDescriptionReference
1685 TypeDescription *type = (TypeDescription *)parameters[i].pTypeRef;
1687 if (parameters[i].bOut != 0)
1689 // FIXME error handling
1690 MapToManaged(ref args[i], unoArgPtrs[i], parameters[i].pTypeRef,
1691 argTypes != null ? argTypes[i] : null, false);
1694 // cleanup args
1695 if (type->eTypeClass < TypeClass.DOUBLE &&
1696 type->eTypeClass != TypeClass.ENUM) // no need to destroy these
1697 uno.Binary.Data.Destroy(unoArgPtrs[i], type, null);
1700 if (returnType != null && returnType->eTypeClass != TypeClass.VOID)
1702 // convert uno return value
1703 object result = null;
1704 // FIXME error handling
1705 MapToManaged(ref result, unoRetPtr, returnType, null, false);
1706 uno.Binary.Data.Destroy(unoRetPtr, (TypeDescription *)returnType, null);
1707 return new uno.Any(MapUnoType(returnType), result); // FIXME is this correct?
1710 return uno.Any.VOID;
1712 else // exception occured
1714 for (int i = 0; i < nParams; ++i)
1715 if (parameters[i].bIn != 0)
1716 uno.Binary.Data.Destroy(unoArgPtrs[i], (TypeDescription *)parameters[i].pTypeRef, null);
1718 // FIXME needs uno.Any vs System.Object clarification
1719 object exc = null;
1720 MapToManaged(ref exc, unoExceptionHolder.pData,
1721 unoExceptionHolder.pType, null, false);
1722 exception = new uno.Any(MapUnoType(unoExceptionHolder.pType), exc);
1723 return uno.Any.VOID;
1726 // FIXME error handling
1729 // FIXME rename, to say what it does, not how it does this
1730 public void RegisterWithCliEnvironment(object managedI, string oid)
1732 managedEnvironment.registerInterface(managedI, oid);
1735 public void RegisterWithCliEnvironment(object managedI, string oid, Type type)
1737 managedEnvironment.registerInterface(managedI, oid, type);
1740 public void RegisterWithUnoEnvironment(ref IntPtr unoInterface, string oid, InterfaceTypeDescription *TD)
1742 UString *unoOid = null;
1743 UString.NewFromString(&unoOid, oid);
1745 uno.Binary.Environment.RegisterInterface(unoEnvironment, ref unoInterface, unoOid, TD);
1747 UString.Release(unoOid);
1750 public void GetInterfaceFromUnoEnvironment(ref IntPtr unoInterface, UString* unoOid, InterfaceTypeDescription* TD)
1752 uno.Binary.Environment.GetRegisteredInterface(unoEnvironment, ref unoInterface, unoOid, TD);
1755 public void RevokeFromUnoEnvironment(IntPtr unoInterface)
1757 throw new NotImplementedException();
1760 public unsafe IntPtr CreateManagedProxy(object managedInterface,
1761 TypeDescription* td,
1762 UString* oid)
1764 // register original interface
1765 RegisterWithCliEnvironment(managedInterface,
1766 UString.UStringToString(oid),
1767 Bridge.MapUnoType(td));
1769 ManagedProxy proxy = new ManagedProxy(this, managedInterface, td, oid);
1770 GCHandle gchandle = GCHandle.Alloc(proxy);
1772 // create binary uno uno_Interface and register proxy with target environment
1773 IntPtr unoI = CreateBinaryProxyAndRegister(unoEnvironment, (IntPtr)gchandle,
1774 oid, td);
1776 proxy.NativeProxy = unoI;
1777 return unoI;
1780 [ DllImport("cli_uno", EntryPoint="cli_uno_environment_createMonoProxyAndRegister") ]
1781 public static unsafe extern IntPtr CreateBinaryProxyAndRegister(
1782 IntPtr unoEnvironment,
1783 IntPtr monoProxy,
1784 /* UString */ void* oid,
1785 /* InterfaceTypeDescription */ void* td);
1787 public unsafe void CallManaged(object managedI, Type ifaceType, MethodInfo method,
1788 TypeDescriptionReference* returnType,
1789 MethodParameter* parameters, int nParams, void* unoRet,
1790 void** unoArgs, uno.Binary.Any** unoExc)
1792 object[] args = new object[nParams];
1793 for (int i = 0; i < nParams; ++i)
1794 if (parameters[i].bIn != 0)
1795 MapToManaged(ref args[i], unoArgs[i], parameters[i].pTypeRef, null, false);
1797 object invocationResult = null;
1798 Exception exc = null;
1801 invocationResult = method.Invoke(managedI, args);
1803 catch (TargetInvocationException e)
1805 exc = e.InnerException;
1807 catch (Exception e)
1809 exc = e;
1811 if ( exc != null )
1813 if ( !( exc is unoidl.com.sun.star.uno.Exception ) )
1815 // #FIXME put more info in here trace, stack etc. ( when I
1816 // figure out how to do that in mono )
1817 exc = new unoidl.com.sun.star.uno.RuntimeException( exc.ToString(), null );
1819 TypeDescription* td = null;
1820 // FIXME leak
1821 TypeDescriptionReference.GetDescription(&td, MapManagedType(exc.GetType()));
1822 void* memExc = uno.rtl.Mem.Allocate(td->nSize);
1823 MapToUno(memExc, exc, /* FIXME !!!*/ (TypeDescription*)td->pWeakRef, false);
1824 (*unoExc)->pType = td->pWeakRef;
1825 (*unoExc)->pData = memExc;
1826 return;
1828 // convert out, in/out params
1829 for (int i = 0; i < nParams; ++i)
1831 if (parameters[i].bOut != 0)
1833 MapToUno(
1834 unoArgs[i], args[i], /* FIXME !!! */(TypeDescription*)parameters[i].pTypeRef,
1835 parameters[i].bIn != 0 /* assign if inout */);
1836 // FIXME error handling
1840 // return value
1841 if (returnType != null)
1842 MapToUno(unoRet, invocationResult, /* FIXME !!! */(TypeDescription*)returnType, false /* no assign */);
1844 // no exception occurred
1845 *unoExc = null;