update dev300-m58
[ooovba.git] / cli_ure / source / mono_bridge / bridge.cs
blobbcab9028ba2b4ec1e2bbb784879b7d4812d142f3
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 namespace com.sun.star.bridges.mono_uno /* FIXME use some uno.foo namespace ? */
65 using System;
66 using System.Reflection;
67 using System.Runtime.InteropServices;
68 using System.Runtime.Remoting;
69 using System.Text;
70 using uno.Binary;
71 using uno.rtl;
72 using uno.Typelib;
74 public unsafe class Bridge
76 static IntPtr unoEnvironment;
77 static cli_uno.Cli_environment managedEnvironment;
79 Bridge(IntPtr unoEnv)
81 unoEnvironment = unoEnv;
82 managedEnvironment = new cli_uno.Cli_environment();
85 public unsafe IntPtr MapManagedToUno(object managedData, TypeDescription *td)
87 IntPtr result = new IntPtr(null);
89 // get oid from managed environment
90 string oid = cli_uno.Cli_environment.getObjectIdentifier(managedData);
92 UString* unoOid = null;
93 UString.NewFromString(&unoOid, oid);
94 uno.Binary.Environment.GetRegisteredInterface(unoEnvironment,
95 ref result,
96 unoOid,
97 (InterfaceTypeDescription *)td);
98 if (result == IntPtr.Zero)
99 lock (typeof(cli_uno.Cli_environment))
101 uno.Binary.Environment.GetRegisteredInterface(unoEnvironment,
102 ref result,
103 unoOid,
104 (InterfaceTypeDescription *)td);
105 if (result == IntPtr.Zero)
106 result = CreateManagedProxy(managedData, td, unoOid);
109 UString.Release(unoOid);
111 return result;
114 public unsafe object MapUnoToManaged(IntPtr unoInterface, InterfaceTypeDescription *iTD)
116 object result = null;
118 UString* oidPtr = null;
119 uno.Binary.Environment.GetObjectIdentifier(unoEnvironment, &oidPtr, unoInterface);
121 // See if the interface was already mapped
122 Type ifaceType = MapUnoType((TypeDescription *)iTD);
123 string oid = UString.UStringToString(oidPtr);
124 // the string is owned by unoEnvironment
125 oidPtr = null;
127 lock (managedEnvironment)
129 result = managedEnvironment.getRegisteredInterface(oid, ifaceType);
130 if (result != null)
132 // There is already an registered object. It can either be a proxy
133 // for the UNO object or a real cli object. In the first case we
134 // tell the proxy that it shall also represent the current UNO
135 // interface. If it already does that, then it does nothing
136 if (RemotingServices.IsTransparentProxy(result))
138 UnoInterfaceProxy p = (UnoInterfaceProxy)RemotingServices.GetRealProxy(result);
139 p.AddUnoInterface(unoInterface, iTD);
142 else
144 result = UnoInterfaceProxy.Create(this, unoInterface, iTD, oid);
148 return result;
151 // FIXME convert cli types to expected types, e.g a long to a short where the uno type
152 // is a sal_Int16. This could be necessary if a scripting language (typeless) is used
153 // @param assign the uno_data has to be destructed (in/out args)
154 unsafe void MapToUno(void *unoData, object managedData,
155 // FIXME it's a TypeDescriptionReference
156 TypeDescription *type, bool assign)
158 // FIXME acquire the TypeDescription?
159 // FIXME assert that all the type equivalences in the comments hold
160 switch (type->eTypeClass)
162 case TypeClass.VOID:
163 break;
164 case TypeClass.CHAR:
165 *(ushort *)unoData = (char)managedData; // sal_Unicode = ushort
166 break;
167 case TypeClass.BOOLEAN:
168 *(byte *)unoData = (bool)managedData ? (byte)1 : (byte)0; // sal_Bool = byte
169 break;
170 case TypeClass.BYTE:
171 *(byte *)unoData = (byte)managedData; // sal_Int8 = byte
172 break;
173 case TypeClass.SHORT:
174 *(short *)unoData = (short)managedData; // sal_Int16 = short
175 break;
176 case TypeClass.UNSIGNED_SHORT:
177 *(ushort *)unoData = (ushort)managedData; // sal_uInt16 = ushort
178 break;
179 case TypeClass.LONG:
180 *(int *)unoData = (int)managedData; // sal_Int32 = int
181 break;
182 case TypeClass.UNSIGNED_LONG:
183 *(uint *)unoData = (uint)managedData; // sal_uInt32 = uint
184 break;
185 case TypeClass.HYPER:
186 *(long *)unoData = (long)managedData; // sal_Int64 = long
187 break;
188 case TypeClass.UNSIGNED_HYPER:
189 *(ulong *)unoData = (ulong)managedData; // sal_uInt64 = ulong
190 break;
191 case TypeClass.FLOAT:
192 *(float *)unoData = (float)managedData; // C++ float = C# float
193 break;
194 case TypeClass.DOUBLE:
195 *(double *)unoData = (double)managedData; // C++ double = C# double
196 break;
197 case TypeClass.STRING:
199 if (assign && *(UString **)unoData != null)
200 UString.Release(*(UString **)unoData);
202 *(UString **)unoData = null;
203 if (managedData == null)
205 UString.New((UString **)unoData);
207 else
209 string s = (string)managedData;
210 UString.NewFromString((UString **)unoData, s);
213 break;
214 case TypeClass.TYPE:
215 if (assign)
216 TypeDescriptionReference.Release(*(TypeDescriptionReference **)unoData);
218 *(TypeDescriptionReference **)unoData = MapManagedType((Type)managedData);
219 break;
220 case TypeClass.ANY:
222 uno.Binary.Any *binAny = (uno.Binary.Any *)unoData;
224 if (assign)
225 uno.Binary.Any.Destroy(binAny, null);
227 if (managedData == null)
229 uno.Binary.Any.Construct(binAny, null, null, null);
230 break;
233 uno.Any any = (uno.Any)managedData;
234 TypeDescription *valueTD = (TypeDescription *)MapManagedType(any.Type);
236 // if there's enough room in void *pReserved, store the value in the pointer
237 binAny->pData = &binAny->pReserved; // this triggers a bug in mcs < 1.1.4
238 switch (valueTD->eTypeClass)
240 case TypeClass.VOID:
241 break;
242 case TypeClass.CHAR:
243 *(ushort *)binAny->pData = (char)any.Value;
244 break;
245 case TypeClass.BOOLEAN:
246 *(byte *)binAny->pData = (bool)any.Value ? (byte)1 : (byte)0;
247 break;
248 case TypeClass.BYTE:
249 *(byte *)binAny->pData = (byte)any.Value;
250 break;
251 case TypeClass.SHORT:
252 *(short *)binAny->pData = (short)any.Value;
253 break;
254 case TypeClass.UNSIGNED_SHORT:
255 *(ushort *)binAny->pData = (ushort)any.Value;
256 break;
257 case TypeClass.LONG:
258 *(int *)binAny->pData = (int)any.Value;
259 break;
260 case TypeClass.UNSIGNED_LONG:
261 *(uint *)binAny->pData = (uint)any.Value;
262 break;
263 case TypeClass.HYPER:
264 if (sizeof(long) > sizeof(void *))
265 binAny->pData = uno.rtl.Mem.Allocate(sizeof(long));
267 *(long *)binAny->pData = (long)any.Value;
268 break;
269 case TypeClass.UNSIGNED_HYPER:
270 if (sizeof(ulong) > sizeof(void *))
271 binAny->pData = uno.rtl.Mem.Allocate(sizeof(ulong));
273 *(ulong *)binAny->pData = (ulong)any.Value;
274 break;
275 case TypeClass.FLOAT:
276 if (sizeof(float) > sizeof(void *)) // FIXME can this happen?
277 binAny->pData = uno.rtl.Mem.Allocate(sizeof(float));
279 *(float *)binAny->pData = (float)any.Value;
280 break;
281 case TypeClass.DOUBLE:
282 if (sizeof(double) > sizeof(void *))
283 binAny->pData = uno.rtl.Mem.Allocate(sizeof(double));
285 *(double *)binAny->pData = (double)any.Value;
286 break;
287 case TypeClass.STRING:
288 // string anies are used so often, that we handle them
289 // separately, to be a little faster than with an
290 // extra MapToUno call
292 // the Any was already destroyed, can't contain a
293 // valid string that we could leak here.
294 *(UString **)binAny->pData = null;
296 if (managedData == null)
298 UString.New((UString **)binAny->pData);
300 else
302 string s = (string)any.Value;
303 UString.NewFromString((UString **)binAny->pData, s);
305 // the string is owned by the Any
306 break;
307 case TypeClass.ENUM:
308 *(int *) binAny->pData = System.Convert.ToInt32(any.Value);
309 break;
310 case TypeClass.TYPE:
311 case TypeClass.SEQUENCE:
312 case TypeClass.INTERFACE:
313 binAny->pReserved = null;
314 MapToUno(binAny->pData, any.Value, valueTD, false /* no assign */);
315 break;
316 case TypeClass.STRUCT:
317 case TypeClass.EXCEPTION:
318 binAny->pData = uno.rtl.Mem.Allocate(valueTD->nSize);
319 MapToUno(binAny->pData, any.Value, valueTD, false /* no assign */);
320 break;
321 default:
322 // FIXME
323 throw new Exception();
325 binAny->pType = (TypeDescriptionReference *)valueTD;
326 TypeDescriptionReference.Acquire(binAny->pType);
328 break;
329 case TypeClass.ENUM:
330 *(int *)unoData = System.Convert.ToInt32(managedData);
331 break;
332 case TypeClass.STRUCT:
333 case TypeClass.EXCEPTION:
335 TypeDescription *td = null; // FIXME leak
336 TypeDescriptionReference.GetDescription(&td, (TypeDescriptionReference *)type);
337 CompoundTypeDescription *compTD = (CompoundTypeDescription *)td;
338 StructTypeDescription *structTD = null;
340 if (type->eTypeClass == TypeClass.STRUCT)
341 structTD = (StructTypeDescription *)type;
343 if (((TypeDescription *)compTD)->bComplete == 0)
344 TypeDescription.Complete((TypeDescription **)&compTD);
346 int members = compTD->nMembers;
347 Type managedType = null;
348 if (managedData != null)
349 managedType = managedData.GetType();
351 if (compTD->pBaseTypeDescription != null)
352 MapToUno(unoData, managedData,
353 (TypeDescription *)((TypeDescription *)compTD->pBaseTypeDescription)->pWeakRef,
354 assign);
356 TypeDescriptionReference *memberType = null;
357 for (int i = 0; i < members; ++i)
359 memberType = compTD->ppTypeRefs[i];
361 object val = null;
362 if (managedData != null)
364 string fieldName = UString.UStringToString(compTD->ppMemberNames[i]);
365 FieldInfo fieldInfo = managedType.GetField(fieldName);
366 // special case for Exception.Message property
367 // The com.sun.star.uno.Exception.Message field is mapped to the
368 // System.Exception property. Type.GetField("Message") returns null
369 if (fieldInfo == null &&
370 UString.UStringToString(type->pTypeName) == "com.sun.star.uno.Exception")
372 // get ExceptionMessage property
373 if (fieldName == "Message")
375 PropertyInfo propInfo = managedType.GetProperty(fieldName);
376 val = propInfo.GetValue(managedData, null);
377 } // FIXME else throw exception
379 else if (fieldInfo != null)
381 val = fieldInfo.GetValue(managedData);
382 } // FIXME else throw exception
385 void *p = (byte *)unoData + compTD->pMemberOffsets[i];
386 // When using polymorphic structs then the parameterized members can be null.
387 // Then we set a default value.
388 bool useDefault = ((structTD != null &&
389 structTD->pParameterizedTypes != null &&
390 structTD->pParameterizedTypes[i] == 1 &&
391 val == null) ||
392 managedData == null);
393 switch (memberType->eTypeClass)
395 case TypeClass.CHAR:
396 if (useDefault)
397 *(ushort *)p = 0;
398 else
399 *(ushort *)p = (char)val;
400 break;
401 case TypeClass.BOOLEAN:
402 if (useDefault)
403 *(byte *)p = (byte)0;
404 else
405 *(byte *)p = (bool)val ? (byte)1 : (byte)0;
406 break;
407 case TypeClass.BYTE:
408 if (useDefault)
409 *(byte *)p = (byte)0;
410 else
411 *(byte *)p = (byte)val;
412 break;
413 case TypeClass.SHORT:
414 if (useDefault)
415 *(short *)p = (short)0;
416 else
417 *(short *)p = (short)val;
418 break;
419 case TypeClass.UNSIGNED_SHORT:
420 if (useDefault)
421 *(ushort *)p = (ushort)0;
422 else
423 *(ushort *)p = (ushort)val;
424 break;
425 case TypeClass.LONG:
426 if (useDefault)
427 *(int *)p = 0;
428 else
429 *(int *)p = (int)val;
430 break;
431 case TypeClass.UNSIGNED_LONG:
432 if (useDefault)
433 *(uint *)p = (uint)0;
434 else
435 *(uint *)p = (uint)val;
436 break;
437 case TypeClass.HYPER:
438 if (useDefault)
439 *(long *)p = (long)0;
440 else
441 *(long *)p = (long)val;
442 break;
443 case TypeClass.UNSIGNED_HYPER:
444 if (useDefault)
445 *(ulong *)p = (ulong)0;
446 else
447 *(ulong *)p = (ulong)val;
448 break;
449 case TypeClass.FLOAT:
450 if (useDefault)
451 *(float *)p = 0.0F;
452 else
453 *(float *)p = (float)val;
454 break;
455 case TypeClass.DOUBLE:
456 if (useDefault)
457 *(double *)p = 0.0;
458 else
459 *(double *)p = (double)val;
460 break;
461 default:
462 // FIXME enum should be converted here
463 MapToUno(p, val, (TypeDescription *)memberType, assign);
464 break;
467 // FIXME exception handling
469 break;
470 case TypeClass.SEQUENCE:
472 TypeDescription *td = null; // FIXME
473 TypeDescriptionReference.GetDescription(&td, (TypeDescriptionReference *)type);
474 TypeDescriptionReference *elementType =
475 ((IndirectTypeDescription *)td)->pType;
477 SequencePtr seq = new SequencePtr();
479 if (managedData != null)
481 Array array = (Array)managedData;
482 int length = array.GetLength(0);
484 switch (elementType->eTypeClass)
486 case TypeClass.CHAR:
487 seq = SequencePtr.Allocate(length, sizeof(ushort));
488 Marshal.Copy((char [])managedData, 0, seq.elementsPtr, length);
489 break;
490 /* case TypeClass.BOOLEAN:
491 // FIXME bool vs. byte ???
492 seq = SequencePtr.Allocate(length, sizeof(byte));
493 Marshal.Copy((byte [])managedData, 0, seq.elementsPtr, length);
494 break;*/
495 case TypeClass.BYTE:
496 seq = SequencePtr.Allocate(length, sizeof(byte));
497 Marshal.Copy((byte [])managedData, 0, seq.elementsPtr, length);
498 break;
499 case TypeClass.SHORT:
500 seq = SequencePtr.Allocate(length, sizeof(short));
501 Marshal.Copy((short [])managedData, 0, seq.elementsPtr, length);
502 break;
503 /* case TypeClass.UNSIGNED_SHORT:
504 seq = SequencePtr.Allocate(length, sizeof(ushort));
505 Marshal.Copy((short [])managedData, 0, seq.elementsPtr, length);
506 break; */
507 case TypeClass.LONG:
508 seq = SequencePtr.Allocate(length, sizeof(int));
509 Marshal.Copy((int [])managedData, 0, seq.elementsPtr, length);
510 break;
511 /* case TypeClass.UNSIGNED_LONG:
512 seq = SequencePtr.Allocate(length, sizeof(uint));
513 Marshal.Copy((int [])managedData, 0, seq.elementsPtr, length);
514 break; */
515 case TypeClass.HYPER:
516 seq = SequencePtr.Allocate(length, sizeof(long));
517 Marshal.Copy((long [])managedData, 0, seq.elementsPtr, length);
518 break;
519 /* case TypeClass.UNSIGNED_HYPER:
520 seq = SequencePtr.Allocate(length, sizeof(ulong));
521 Marshal.Copy((long [])managedData, 0, seq.elementsPtr, length);
522 break; */
523 case TypeClass.FLOAT:
524 seq = SequencePtr.Allocate(length, sizeof(float));
525 Marshal.Copy((float [])managedData, 0, seq.elementsPtr, length);
526 break;
527 case TypeClass.DOUBLE:
528 seq = SequencePtr.Allocate(length, sizeof(double));
529 Marshal.Copy((double [])managedData, 0, seq.elementsPtr, length);
530 break;
531 case TypeClass.STRING:
533 seq = SequencePtr.Allocate(length, sizeof(void *));
534 string[] stringArray = (string [])managedData;
535 for (int i = 0; i < length; ++i)
537 UString** pStr = ((UString** )seq.elementsPtr) + i;
538 *pStr = null;
539 UString.NewFromString(pStr, stringArray[i]);
540 // string ownership goes to callee
543 break;
544 case TypeClass.ENUM:
545 seq = SequencePtr.Allocate(length, sizeof(int));
546 for (int i = 0; i < length; ++i)
547 ((int *)seq.elementsPtr)[i] =
548 Convert.ToInt32(array.GetValue(i));
549 break;
550 case TypeClass.TYPE:
551 case TypeClass.ANY:
552 case TypeClass.STRUCT:
553 case TypeClass.EXCEPTION:
554 case TypeClass.SEQUENCE:
555 case TypeClass.INTERFACE:
556 // FIXME: surely we can do better for this lot [!] - sign problems ...
557 case TypeClass.BOOLEAN:
558 case TypeClass.UNSIGNED_SHORT:
559 case TypeClass.UNSIGNED_LONG:
560 case TypeClass.UNSIGNED_HYPER:
562 seq = SequencePtr.Allocate(
563 length, ((TypeDescription *)elementType)->nSize);
565 for (int i = 0; i < length; ++i)
567 void *p =
568 (byte *)seq.elementsPtr +
569 i * ((TypeDescription *)elementType)->nSize;
570 object elementData = ((Array)managedData).GetValue(i);
571 MapToUno(p, elementData,
572 (TypeDescription *)((TypeDescription *)elementType)->pWeakRef,
573 false /* no assign */);
575 // FIXME exception handling
577 break;
578 default:
579 break; // FIXME throw some exception
582 else
584 seq = SequencePtr.Allocate(0, sizeof(int));
586 *(SequencePtr *)unoData = seq;
588 break;
589 case TypeClass.INTERFACE:
591 if (assign && *(void **)unoData != null)
592 uno.Binary.Interface.Release(new IntPtr(*(void **)unoData));
594 if (managedData == null)
595 *(void **)unoData = null;
596 else
598 TypeDescription *td = null; // FIXME leak
599 TypeDescriptionReference.GetDescription(&td, (TypeDescriptionReference *)type);
600 *(void **)unoData = MapManagedToUno(managedData, td).ToPointer();
602 break;
604 default:
605 // FIXME throw some exception
606 break;
610 unsafe void MapToManaged(ref object managedData, void *unoData,
611 TypeDescriptionReference *type, Type info, bool dontCreateObj)
613 switch (type->eTypeClass)
615 case TypeClass.CHAR:
616 managedData = (char)*(ushort *)unoData;
617 break;
618 case TypeClass.BOOLEAN:
619 managedData = (*(byte *)unoData != 0);
620 break;
621 case TypeClass.BYTE:
622 managedData = *(byte *)unoData;
623 break;
624 case TypeClass.SHORT:
625 managedData = *(short *)unoData;
626 break;
627 case TypeClass.UNSIGNED_SHORT:
628 managedData = *(ushort *)unoData;
629 break;
630 case TypeClass.LONG:
631 managedData = *(int *)unoData;
632 break;
633 case TypeClass.UNSIGNED_LONG:
634 managedData = *(uint *)unoData;
635 break;
636 case TypeClass.HYPER:
637 managedData = *(long *)unoData;
638 break;
639 case TypeClass.UNSIGNED_HYPER:
640 managedData = *(ulong *)unoData;
641 break;
642 case TypeClass.FLOAT:
643 managedData = *(float *)unoData;
644 break;
645 case TypeClass.DOUBLE:
646 managedData = *(double *)unoData;
647 break;
648 case TypeClass.STRING:
649 managedData = UString.UStringToString(*(UString **)unoData);
650 break;
651 case TypeClass.TYPE:
652 managedData = MapUnoType(*(TypeDescriptionReference **)unoData);
653 break;
654 case TypeClass.ANY:
656 uno.Binary.Any *binAny = (uno.Binary.Any *)unoData;
657 if (binAny->pType->eTypeClass != TypeClass.VOID)
659 object value = null;
660 MapToManaged(ref value, binAny->pData, binAny->pType, null, false);
661 managedData = new uno.Any(MapUnoType(binAny->pType), value);
663 else
665 managedData = uno.Any.VOID;
667 break;
669 case TypeClass.ENUM:
670 if (info != null)
671 managedData = Enum.ToObject(
672 info.GetElementType(), *(int *)unoData);
673 else
674 managedData = Enum.ToObject(
675 MapUnoType(type), *(int *)unoData);
676 break;
677 case TypeClass.STRUCT:
678 case TypeClass.EXCEPTION:
680 TypeDescription *td = null; // FIXME leak
681 TypeDescriptionReference.GetDescription(&td, (TypeDescriptionReference *)type);
682 CompoundTypeDescription *compTD = (CompoundTypeDescription *)td;
684 if (((TypeDescription *)compTD)->bComplete == 0)
685 TypeDescription.Complete((TypeDescription **)&compTD);
687 // create the type
688 Type managedType = LoadCliType(td->pTypeName);
690 // detect if we recursivly convert inherited
691 // structures. If this point is reached because of a
692 // recursive call during converting a struct then we must
693 // not create a new object rather we use the one in
694 // cli_data argument.
695 object managedObject;
696 if (dontCreateObj)
697 managedObject = managedData;
698 else
700 // Special handling for Exception conversion. We must
701 // call constructor System::Exception to pass the
702 // message string
703 if (typeof(unoidl.com.sun.star.uno.Exception).IsAssignableFrom(managedType))
705 // We need to get the Message field. Therefore we
706 // must obtain the offset from the
707 // typedescription. The base interface of all
708 // exceptions is com::sun::star::uno::Exception
709 // which contains the message
710 CompoundTypeDescription *pCTD = compTD;
711 while (pCTD->pBaseTypeDescription != null)
712 pCTD = pCTD->pBaseTypeDescription;
714 int pos = -1;
715 for (int i = 0; i < pCTD->nMembers; ++i)
717 if (UString.UStringToString(pCTD->ppMemberNames[i]) == "Message")
719 pos = i;
720 break;
724 int offset = pCTD->pMemberOffsets[pos];
725 // With the offset within the exception we can get
726 // the message string
727 string message = UString.UStringToString(
728 (*(UString **)((byte *)unoData + offset)));
729 // We need to find a constructor for the exception
730 // that takes the message string. We assume that
731 // the first argument is the message string
732 ConstructorInfo[] ctorInfos = managedType.GetConstructors();
733 ConstructorInfo ctorInfo = null;
734 // Constructor must at least have 2 params for the base
735 // unoidl.com.sun.star.uno.Exception (String, Object);
736 int numArgs = -1;
737 foreach (ConstructorInfo ci in ctorInfos)
739 numArgs = ci.GetParameters().Length;
740 if (numArgs < 2)
741 continue;
742 ctorInfo = ci;
743 break;
746 // Prepare parameters for constructor
747 object[] args = new object[numArgs];
748 // only initialize the first argument with the
749 // message. All unoidl.<Foo Exception>s are
750 // autogenerated, we know that this is safe.
751 args[0] = message;
752 managedObject = ctorInfo.Invoke(args);
754 else
755 managedObject = Activator.CreateInstance(managedType);
758 TypeDescriptionReference **memberTypeRefs = compTD->ppTypeRefs;
759 int *memberOffsets = compTD->pMemberOffsets;
761 if (compTD->pBaseTypeDescription != null)
763 // convert inherited struct
764 // cliObj is passed inout (args in_param, out_param are true), hence the passed
765 // cliObj is used by the callee instead of a newly created struct
766 MapToManaged(ref managedObject, unoData,
767 ((TypeDescription *)compTD->pBaseTypeDescription)->pWeakRef,
768 null,
769 true);
771 for (int i = compTD->nMembers - 1; i >= 0; --i)
773 TypeDescriptionReference *memberType = memberTypeRefs[i];
774 string memberName = UString.UStringToString(compTD->ppMemberNames[i]);
775 FieldInfo fieldInfo = managedType.GetField(memberName);
776 // special case for Exception.Message. The field has already been
777 // set while constructing cli object
778 if (fieldInfo == null &&
779 UString.UStringToString(type->pTypeName) == "com.sun.star.uno.Exception")
780 continue;
782 void *p = (byte *)unoData + memberOffsets[i];
783 switch (memberType->eTypeClass)
785 case TypeClass.CHAR:
786 fieldInfo.SetValue(managedObject, (char)*(short *)p);
787 break;
788 case TypeClass.BOOLEAN:
789 fieldInfo.SetValue(managedObject, (*(byte *)p) != 0);
790 break;
791 case TypeClass.BYTE:
792 fieldInfo.SetValue(managedObject, *(byte *)p);
793 break;
794 case TypeClass.SHORT:
795 fieldInfo.SetValue(managedObject, *(short *)p);
796 break;
797 case TypeClass.UNSIGNED_SHORT:
798 fieldInfo.SetValue(managedObject, *(ushort *)p);
799 break;
800 case TypeClass.LONG:
801 fieldInfo.SetValue(managedObject, *(int *)p);
802 break;
803 case TypeClass.UNSIGNED_LONG:
804 fieldInfo.SetValue(managedObject, *(uint *)p);
805 break;
806 case TypeClass.HYPER:
807 fieldInfo.SetValue(managedObject, *(long *)p);
808 break;
809 case TypeClass.UNSIGNED_HYPER:
810 fieldInfo.SetValue(managedObject, *(ulong *)p);
811 break;
812 case TypeClass.FLOAT:
813 fieldInfo.SetValue(managedObject, *(float *)p);
814 break;
815 case TypeClass.DOUBLE:
816 fieldInfo.SetValue(managedObject, *(double *)p);
817 break;
818 default:
820 object managedValue = null;
821 MapToManaged(ref managedValue, p, memberType, null, false);
822 fieldInfo.SetValue(managedObject, managedValue);
823 break;
827 managedData = managedObject;
828 break;
830 case TypeClass.SEQUENCE:
832 SequencePtr seq = *(SequencePtr *)unoData;
833 int length = seq.nElements;
835 TypeDescription *td = null; // FIXME leak
836 TypeDescriptionReference.GetDescription(&td, (TypeDescriptionReference *)type);
837 TypeDescriptionReference *elementType = ((IndirectTypeDescription *)td)->pType;
839 switch (elementType->eTypeClass)
841 case TypeClass.CHAR:
843 char[] array = new char[length];
844 Marshal.Copy(seq.elementsPtr, array, 0, length);
845 managedData = array;
846 break;
848 case TypeClass.BOOLEAN:
850 bool[] array = new bool[length];
851 byte *source = (byte *)seq.elementsPtr;
852 if (length > 0) fixed (bool *arrayPtr = array)
854 bool *dest = arrayPtr;
855 for (int i = 0; i < length; ++i)
856 *dest++ = (*source++ != 0);
858 managedData = array;
859 break;
861 case TypeClass.BYTE:
863 byte[] array = new byte[length];
864 byte *source = (byte *)seq.elementsPtr;
865 if (length > 0) fixed (byte *arrayPtr = array)
867 byte *dest = arrayPtr;
868 for (int i = 0; i < length; ++i)
869 *dest++ = *source++;
871 managedData = array;
872 break;
874 case TypeClass.SHORT:
876 short[] array = new short[length];
877 Marshal.Copy(seq.elementsPtr, array, 0, length);
878 managedData = array;
879 break;
881 case TypeClass.UNSIGNED_SHORT:
883 ushort[] array = new ushort[length];
884 ushort *source = (ushort *)seq.elementsPtr;
885 if (length > 0) fixed (ushort *arrayPtr = array)
887 ushort *dest = arrayPtr;
888 for (int i = 0; i < length; ++i)
889 *dest++ = *source++;
891 managedData = array;
892 break;
894 case TypeClass.LONG:
896 int[] array = new int[length];
897 Marshal.Copy(seq.elementsPtr, array, 0, length);
898 managedData = array;
899 break;
901 case TypeClass.UNSIGNED_LONG:
903 uint[] array = new uint[length];
904 uint *source = (uint *)seq.elementsPtr;
905 if (length > 0) fixed (uint *arrayPtr = array)
907 uint *dest = arrayPtr;
908 for (int i = 0; i < length; ++i)
909 *dest++ = *source++;
911 managedData = array;
912 break;
914 case TypeClass.HYPER:
916 long[] array = new long[length];
917 Marshal.Copy(seq.elementsPtr, array, 0, length);
918 managedData = array;
919 break;
921 case TypeClass.UNSIGNED_HYPER:
923 ulong[] array = new ulong[length];
924 ulong *source = (ulong *)seq.elementsPtr;
925 if (length > 0) fixed (ulong *arrayPtr = array)
927 ulong *dest = arrayPtr;
928 for (int i = 0; i < length; ++i)
929 *dest++ = *source++;
931 managedData = array;
932 break;
934 case TypeClass.FLOAT:
936 float[] array = new float[length];
937 Marshal.Copy(seq.elementsPtr, array, 0, length);
938 managedData = array;
939 break;
941 case TypeClass.DOUBLE:
943 double[] array = new double[length];
944 Marshal.Copy(seq.elementsPtr, array, 0, length);
945 managedData = array;
946 break;
948 case TypeClass.STRING:
950 string[] array = new string[length];
951 for (int i = 0; i < length; ++i)
953 UString *us = ((UString **)seq.elementsPtr)[i];
954 array[i] = UString.UStringToString(us);
956 managedData = array;
957 break;
959 case TypeClass.TYPE:
961 Type[] array = new Type[length];
962 for (int i = 0; i < length; ++i)
963 array[i] = MapUnoType(((TypeDescriptionReference **)
964 seq.elementsPtr)[i]);
965 managedData = array;
966 break;
968 case TypeClass.ANY:
970 uno.Any[] array = new uno.Any[length];
971 uno.Binary.Any *binAny = (uno.Binary.Any *)seq.elementsPtr;
972 for (int i = 0; i < length; ++i)
974 object any = new uno.Any();
975 MapToManaged(ref any, (void **)(binAny + i),
976 (TypeDescriptionReference *)elementType,
977 null, false);
978 array[i] = (uno.Any)any;
980 managedData = array;
981 break;
983 case TypeClass.ENUM:
985 Type enumType = null;
986 if (info != null)
988 enumType = info.GetElementType();
989 // enumType is EnumType[], get EnumType
990 enumType = enumType.GetElementType();
992 else
993 enumType = MapUnoType(elementType);
995 Array array = Array.CreateInstance(enumType, length);
996 for (int i = 0; i < length; ++i)
998 array.SetValue(Enum.ToObject(enumType,
999 ((int *)seq.elementsPtr)[i]),
1002 managedData = array;
1003 break;
1005 case TypeClass.STRUCT:
1006 case TypeClass.EXCEPTION:
1008 Array array = Array.CreateInstance(MapUnoType(elementType), length);
1009 if (length > 0)
1011 // FIXME check this
1012 byte *p = (byte *)seq.elementsPtr;
1013 int size = ((TypeDescription *)elementType)->nSize;
1014 for (int i = 0; i < length; ++i)
1016 object val = null;
1017 MapToManaged(ref val, p + (size * i), elementType, null, false);
1018 array.SetValue(val, i);
1021 managedData = array;
1022 break;
1024 // FIXME verify (says cli_data.cxx)
1025 case TypeClass.SEQUENCE:
1027 Array array = Array.CreateInstance(
1028 MapUnoType(elementType), length);
1029 if (length > 0)
1031 SequencePtr *elements = (SequencePtr *)seq.elementsPtr;
1032 for (int i = 0; i < length; ++i)
1034 object val = null;
1035 MapToManaged(ref val, elements + i, elementType, null, false);
1036 array.SetValue(val, i);
1039 managedData = array;
1040 break;
1042 case TypeClass.INTERFACE:
1044 Type ifaceType = MapUnoType(elementType);
1045 Array array = Array.CreateInstance(ifaceType, length);
1047 byte *p = (byte *)seq.elementsPtr;
1048 int size = ((TypeDescription *)elementType)->nSize;
1049 for (int i = 0; i < length; ++i)
1051 object val = null;
1052 MapToManaged(ref val, p + (size * i), elementType, null, false);
1053 array.SetValue(val, i);
1055 managedData = array;
1056 break;
1058 default:
1060 // FIXME throw some exception
1061 break;
1064 break;
1066 case TypeClass.INTERFACE:
1068 IntPtr unoI = new IntPtr(*(void **)unoData);
1069 if (unoI != IntPtr.Zero)
1071 TypeDescription *td = null; // FIXME leak
1072 TypeDescriptionReference.GetDescription(&td, type);
1073 managedData = MapUnoToManaged(unoI, (InterfaceTypeDescription *)td);
1075 else
1076 managedData = null;
1077 break;
1079 default:
1081 // FIXME throw some exception
1082 break;
1087 public static Type MapUnoType(TypeDescription *TD)
1089 return MapUnoType(TD->pWeakRef);
1092 public static Type MapUnoType(TypeDescriptionReference *TD)
1094 Type result;
1096 switch(TD->eTypeClass)
1098 case TypeClass.VOID:
1099 result = typeof(void);
1100 break;
1101 case TypeClass.CHAR:
1102 result = typeof(char);
1103 break;
1104 case TypeClass.BOOLEAN:
1105 result = typeof(bool);
1106 break;
1107 case TypeClass.BYTE:
1108 result = typeof(byte);
1109 break;
1110 case TypeClass.SHORT:
1111 result = typeof(short);
1112 break;
1113 case TypeClass.UNSIGNED_SHORT:
1114 result = typeof(ushort);
1115 break;
1116 case TypeClass.LONG:
1117 result = typeof(int);
1118 break;
1119 case TypeClass.UNSIGNED_LONG:
1120 result = typeof(uint);
1121 break;
1122 case TypeClass.HYPER:
1123 result = typeof(long);
1124 break;
1125 case TypeClass.UNSIGNED_HYPER:
1126 result = typeof(ulong);
1127 break;
1128 case TypeClass.FLOAT:
1129 result = typeof(float);
1130 break;
1131 case TypeClass.DOUBLE:
1132 result = typeof(double);
1133 break;
1134 case TypeClass.STRING:
1135 result = typeof(string);
1136 break;
1137 case TypeClass.TYPE:
1138 result = typeof(Type);
1139 break;
1140 case TypeClass.ANY:
1141 result = typeof(uno.Any);
1142 break;
1143 case TypeClass.ENUM:
1144 case TypeClass.STRUCT:
1145 case TypeClass.EXCEPTION:
1146 result = LoadCliType(TD->pTypeName);
1147 break;
1148 case TypeClass.INTERFACE:
1149 // special handling for XInterface, since it does not exist in cli.
1150 if (UString.UStringToString(TD->pTypeName) == "com.sun.star.uno.XInterface")
1151 result = typeof(object);
1152 else
1153 result = LoadCliType(TD->pTypeName);
1154 break;
1155 case TypeClass.SEQUENCE:
1157 TypeDescription *seqType = null; // FIXME leak
1158 TypeDescriptionReference.GetDescription(&seqType, TD);
1160 // FIXME do something with TD here?
1161 TypeDescriptionReference *elementTDRef =
1162 ((IndirectTypeDescription *)seqType)->pType;
1164 switch (elementTDRef->eTypeClass)
1166 case TypeClass.CHAR:
1167 result = Type.GetType("System.Char[]");
1168 break;
1169 case TypeClass.BOOLEAN:
1170 result = Type.GetType("System.Boolean[]");
1171 break;
1172 case TypeClass.BYTE:
1173 result = Type.GetType("System.Byte[]");
1174 break;
1175 case TypeClass.SHORT:
1176 result = Type.GetType("System.Int16[]");
1177 break;
1178 case TypeClass.UNSIGNED_SHORT:
1179 result = Type.GetType("System.UInt16[]");
1180 break;
1181 case TypeClass.LONG:
1182 result = Type.GetType("System.Int32[]");
1183 break;
1184 case TypeClass.UNSIGNED_LONG:
1185 result = Type.GetType("System.UInt32[]");
1186 break;
1187 case TypeClass.HYPER:
1188 result = Type.GetType("System.Int64[]");
1189 break;
1190 case TypeClass.UNSIGNED_HYPER:
1191 result = Type.GetType("System.UInt64[]");
1192 break;
1193 case TypeClass.FLOAT:
1194 result = Type.GetType("System.Single[]");
1195 break;
1196 case TypeClass.DOUBLE:
1197 result = Type.GetType("System.Double[]");
1198 break;
1199 case TypeClass.STRING:
1200 result = Type.GetType("System.String[]");
1201 break;
1202 case TypeClass.TYPE:
1203 result = Type.GetType("System.Type[]");
1204 break;
1205 case TypeClass.ANY:
1206 case TypeClass.ENUM:
1207 case TypeClass.EXCEPTION:
1208 case TypeClass.STRUCT:
1209 case TypeClass.INTERFACE:
1210 case TypeClass.SEQUENCE:
1211 result = LoadCliType(TD->pTypeName);
1212 break;
1213 default:
1214 // FIXME can't happen
1215 result = null;
1216 break;
1218 break;
1220 default:
1221 // FIXME can't happen
1222 result = null;
1223 break;
1225 return result;
1228 public static Type LoadCliType(UString* unoName)
1230 return LoadCliType(MapUnoTypeName(UString.UStringToString(unoName)));
1233 public static Type LoadCliType(string unoName)
1235 Type result = null;
1236 bool isPolymorphic = false;
1238 string loadName = unoName;
1239 int index = unoName.IndexOf('<');
1240 if (index != -1)
1242 loadName = unoName.Substring(0, index);
1243 isPolymorphic = true;
1246 result = Type.GetType(loadName + ",cli_uretypes");
1248 if (result == null)
1249 result = Type.GetType(loadName + ",cli_basetypes");
1251 if (result == null)
1252 result = Type.GetType(loadName, false);
1254 if (result == null)
1256 foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
1258 result = a.GetType(loadName, false);
1259 if (result != null)
1260 break;
1264 if (result == null)
1265 // FIXME don't use generic Exception type
1266 throw new Exception("A type could not be loaded: " + loadName);
1268 if (isPolymorphic)
1269 result = uno.PolymorphicType.GetType(result, unoName);
1271 return result;
1274 static TypeDescriptionReference *MapManagedType(Type managedType)
1276 TypeDescriptionReference *result = null;
1277 if (managedType == null)
1279 result = *TypeDescriptionReference.GetByTypeClass(TypeClass.VOID);
1280 TypeDescriptionReference.Acquire(result);
1281 return result;
1284 // check for Enum first,
1285 // because otherwise case System.TypeCode.Int32 applies
1286 if (managedType.IsEnum)
1288 UString* unoTypeName = MapManagedTypeName(managedType.FullName);
1289 TypeDescriptionReference.New(&result, TypeClass.ENUM, unoTypeName);
1290 TypeDescriptionReference.Acquire(result);
1292 else
1294 switch (System.Type.GetTypeCode(managedType))
1296 case System.TypeCode.Boolean:
1297 result = *TypeDescriptionReference.GetByTypeClass(TypeClass.BOOLEAN);
1298 TypeDescriptionReference.Acquire(result);
1299 break;
1300 case System.TypeCode.Char:
1301 result = *TypeDescriptionReference.GetByTypeClass(TypeClass.CHAR);
1302 TypeDescriptionReference.Acquire(result);
1303 break;
1304 case System.TypeCode.Byte:
1305 result = *TypeDescriptionReference.GetByTypeClass(TypeClass.BYTE);
1306 TypeDescriptionReference.Acquire(result);
1307 break;
1308 case System.TypeCode.Int16:
1309 result = *TypeDescriptionReference.GetByTypeClass(TypeClass.SHORT);
1310 TypeDescriptionReference.Acquire(result);
1311 break;
1312 case System.TypeCode.Int32:
1313 result = *TypeDescriptionReference.GetByTypeClass(TypeClass.LONG);
1314 TypeDescriptionReference.Acquire(result);
1315 break;
1316 case System.TypeCode.Int64:
1317 result = *TypeDescriptionReference.GetByTypeClass(TypeClass.HYPER);
1318 TypeDescriptionReference.Acquire(result);
1319 break;
1320 case System.TypeCode.UInt16:
1321 result = *TypeDescriptionReference.GetByTypeClass(TypeClass.UNSIGNED_SHORT);
1322 TypeDescriptionReference.Acquire(result);
1323 break;
1324 case System.TypeCode.UInt32:
1325 result = *TypeDescriptionReference.GetByTypeClass(TypeClass.UNSIGNED_LONG);
1326 TypeDescriptionReference.Acquire(result);
1327 break;
1328 case System.TypeCode.UInt64:
1329 result = *TypeDescriptionReference.GetByTypeClass(TypeClass.UNSIGNED_HYPER);
1330 TypeDescriptionReference.Acquire(result);
1331 break;
1332 case System.TypeCode.Single:
1333 result = *TypeDescriptionReference.GetByTypeClass(TypeClass.FLOAT);
1334 TypeDescriptionReference.Acquire(result);
1335 break;
1336 case System.TypeCode.Double:
1337 result = *TypeDescriptionReference.GetByTypeClass(TypeClass.DOUBLE);
1338 TypeDescriptionReference.Acquire(result);
1339 break;
1340 case System.TypeCode.String:
1341 result = *TypeDescriptionReference.GetByTypeClass(TypeClass.STRING);
1342 TypeDescriptionReference.Acquire(result);
1343 break;
1347 if (result == null)
1349 string managedTypeName = managedType.FullName;
1350 if (managedTypeName == "System.Void")
1352 result = *TypeDescriptionReference.GetByTypeClass(TypeClass.VOID);
1353 TypeDescriptionReference.Acquire(result);
1355 else if (managedTypeName == "System.Type")
1357 result = *TypeDescriptionReference.GetByTypeClass(TypeClass.TYPE);
1358 TypeDescriptionReference.Acquire(result);
1360 else if (managedTypeName == "uno.Any")
1362 result = *TypeDescriptionReference.GetByTypeClass(TypeClass.ANY);
1363 TypeDescriptionReference.Acquire(result);
1365 else
1367 UString* unoTypeName;
1369 uno.PolymorphicType poly = managedType as uno.PolymorphicType;
1370 if (poly != null)
1371 unoTypeName = MapManagedTypeName(poly.PolymorphicName);
1372 else
1373 unoTypeName = MapManagedTypeName(managedTypeName);
1375 TypeDescription *td = null;
1376 TypeDescription.GetByName(&td, unoTypeName);
1377 if (td != null)
1379 result = td->pWeakRef;
1380 TypeDescriptionReference.Acquire(result);
1381 TypeDescription.Release(td);
1386 if (result == null)
1388 // FIXME - quite probably we should throw an exception here instead.
1389 result = *TypeDescriptionReference.GetByTypeClass(TypeClass.VOID);
1390 TypeDescriptionReference.Acquire(result);
1393 return result;
1396 static string MapUnoTypeName(string typeName)
1398 StringBuilder buf = new StringBuilder();
1400 // determine if the type is a sequence and its dimensions
1401 int dims = 0;
1402 if (typeName[0] == '[')
1404 int index = 1;
1405 while (true)
1407 if (typeName[index++] == ']')
1408 ++dims;
1409 if (typeName[index++] != '[')
1410 break;
1412 typeName = typeName.Substring(index - 1);
1415 switch (typeName)
1417 case "boolean":
1418 buf.Append("System.Boolean");
1419 break;
1420 case "char":
1421 buf.Append("System.Char");
1422 break;
1423 case "byte":
1424 buf.Append("System.Byte");
1425 break;
1426 case "short":
1427 buf.Append("System.Int16");
1428 break;
1429 case "unsigned short":
1430 buf.Append("System.UInt16");
1431 break;
1432 case "long":
1433 buf.Append("System.Int32");
1434 break;
1435 case "unsigned long":
1436 buf.Append("System.UInt32");
1437 break;
1438 case "hyper":
1439 buf.Append("System.Int64");
1440 break;
1441 case "unsigned hyper":
1442 buf.Append("System.UInt64");
1443 break;
1444 case "float":
1445 buf.Append("System.Single");
1446 break;
1447 case "double":
1448 buf.Append("System.Double");
1449 break;
1450 case "string":
1451 buf.Append("System.String");
1452 break;
1453 case "void":
1454 buf.Append("System.Void");
1455 break;
1456 case "type":
1457 buf.Append("System.Type");
1458 break;
1459 case "com.sun.star.uno.XInterface":
1460 buf.Append("System.Object");
1461 break;
1462 case "any":
1463 buf.Append("uno.Any");
1464 break;
1465 default:
1466 // put "unoidl." at the beginning
1467 buf.Append("unoidl.");
1468 // for polymorphic struct types remove the brackets, e.g. mystruct<bool> -> mystruct
1469 buf.Append(MapUnoPolymorphicName(typeName));
1470 break;
1473 // append []
1474 for ( ; dims > 0; --dims)
1475 buf.Append("[]");
1477 return buf.ToString();
1480 /** For example, there is a uno type
1481 com.sun.star.Foo<char, long>.
1482 The values in the type list
1483 are uno types and are replaced by cli types, such as System.Char,
1484 System.Int32, etc.
1486 static string MapUnoPolymorphicName(string unoName)
1488 int startIndex = unoName.LastIndexOf('<');
1489 if (startIndex == -1)
1490 return unoName;
1492 // get the type list within < and >
1493 int endIndex = unoName.LastIndexOf('>');
1494 string list = unoName.Substring(startIndex + 1, endIndex - startIndex - 1);
1496 // parse the type list and replace the types with the corresponding CLI types
1497 char[] delimiters = new char[] { ',' };
1498 string[] unoTypes = list.Split(delimiters);
1500 StringBuilder builder = new StringBuilder(unoName.Substring(0, startIndex + 1));
1502 int typeCount = unoTypes.Length;
1503 for (int i = 0; i < typeCount; ++i)
1504 builder.Append(MapUnoTypeName(unoTypes[i]));
1506 builder.Append('>');
1507 return builder.ToString();
1510 static UString* MapManagedTypeName(string typeName)
1512 int dims = 0;
1513 int index = 0;
1515 if ((index = typeName.IndexOf("[]")) > 0)
1517 dims = 1;
1519 int curIndex = index;
1520 while ((curIndex + 2) < typeName.Length &&
1521 (curIndex = typeName.IndexOf("[]", curIndex + 2)) > 0)
1522 ++dims;
1524 // get the element name by removing the brackets
1525 typeName = typeName.Substring(0, index);
1528 StringBuilder buf = new StringBuilder(256);
1529 for (; dims > 0; --dims)
1530 buf.Append("[]");
1532 switch (typeName)
1534 case "System.Boolean":
1535 buf.Append("boolean");
1536 break;
1537 case "System.Char":
1538 buf.Append("char");
1539 break;
1540 case "System.Byte":
1541 buf.Append("byte");
1542 break;
1543 case "System.Int16":
1544 buf.Append("short");
1545 break;
1546 case "System.UInt16":
1547 buf.Append("unsigned short");
1548 break;
1549 case "System.Int32":
1550 buf.Append("long");
1551 break;
1552 case "System.UInt32":
1553 buf.Append("unsigned long");
1554 break;
1555 case "System.Int64":
1556 buf.Append("hyper");
1557 break;
1558 case "System.UInt64":
1559 buf.Append("unsigned hyper");
1560 break;
1561 case "System.Single":
1562 buf.Append("float");
1563 break;
1564 case "System.Double":
1565 buf.Append("double");
1566 break;
1567 case "System.String":
1568 buf.Append("string");
1569 break;
1570 case "System.Void":
1571 buf.Append("void");
1572 break;
1573 case "System.Type":
1574 buf.Append("type");
1575 break;
1576 case "System.Object":
1577 buf.Append("com.sun.star.uno.XInterface");
1578 break;
1579 case "uno.Any":
1580 buf.Append("any");
1581 break;
1582 default:
1584 string name = MapManagedPolymorphicName(typeName);
1585 int i = name.IndexOf('.');
1586 buf.Append(name.Substring(i + 1));
1587 break;
1591 UString *rtl_uString = null;
1592 UString.NewFromStringBuilder(&rtl_uString, buf);
1593 return rtl_uString;
1596 static string MapManagedPolymorphicName(string unoName)
1598 int startIndex = unoName.LastIndexOf('<');
1599 if (startIndex == -1)
1600 return unoName;
1602 // get the type list withing < and >
1603 int endIndex = unoName.LastIndexOf('>');
1604 string list = unoName.Substring(startIndex + 1, endIndex - startIndex - 1);
1606 // parse the type list and replace the types with the corresponding CLI types
1607 char[] delimiters = new char[] { ',' };
1608 string[] unoTypes = list.Split(delimiters);
1610 StringBuilder builder = new StringBuilder(unoName.Substring(0, startIndex + 1));
1612 int typeCount = unoTypes.Length;
1613 for (int i = 0; i < typeCount; ++i)
1614 builder.Append(UString.UStringToString(MapManagedTypeName(unoTypes[i])));
1615 builder.Append('>');
1616 return builder.ToString();
1619 [StructLayout(LayoutKind.Explicit)]
1620 private unsafe struct largest
1622 [FieldOffset(0)] long n;
1623 [FieldOffset(0)] double d;
1624 [FieldOffset(0)] void *p;
1625 [FieldOffset(0)] uno.Binary.Any a;
1628 // FIXME args[i] must be of same type as return value
1629 public unsafe uno.Any CallUno(IntPtr unoInterface, TypeDescription *memberTD,
1630 TypeDescriptionReference *returnType, int nParams,
1631 MethodParameter *parameters, object[] args,
1632 Type[] argTypes, out uno.Any exception)
1634 int returnSize = sizeof(largest);
1636 if (returnType != null &&
1637 (returnType->eTypeClass == TypeClass.STRUCT ||
1638 returnType->eTypeClass == TypeClass.EXCEPTION))
1640 // FIXME leak
1641 TypeDescription *td = null;
1642 TypeDescriptionReference.GetDescription(&td, returnType);
1644 if (td->nSize > returnSize)
1645 returnSize = td->nSize;
1648 // Prepare memory that contains all converted arguments and
1649 // return values. The memory block contains first pointers to
1650 // the arguments which are in the same block For example, 2
1651 // arguments, 1 ret.
1653 // | Pointer
1654 // | Pointer
1655 // | Return value
1656 // | Arg 1
1657 // | Arg 2
1659 // If an argument is larger then struct largest, such as some
1660 // structures, then the pointer points to an extra block of
1661 // memory. The same goes for a big return value.
1662 // FIXME the last sentence is bullshit. Get it deleted from cli_uno ;)
1663 byte *mem = stackalloc byte[nParams * sizeof(void *) +
1664 returnSize +
1665 nParams * sizeof(largest)];
1667 // array of pointers to args
1668 void **unoArgPtrs = (void **)mem;
1670 // Return Value
1671 void *unoRetPtr = null;
1672 largest *unoArgs = (largest *)(unoArgPtrs + nParams);
1673 if (memberTD->eTypeClass != TypeClass.INTERFACE_ATTRIBUTE || nParams != 1)
1675 // If an attribute is set, then unoRet must be null, e.g. void setAttribute(int)
1676 unoRetPtr = (void *)unoArgs;
1677 unoArgs = (largest *)((byte *)unoRetPtr + returnSize);
1680 for (int i = 0; i < nParams; ++i)
1682 // FIXME it's a TypeDescriptionReference
1683 TypeDescription *type = (TypeDescription *)parameters[i].pTypeRef;
1685 unoArgPtrs[i] = unoArgs + i;
1686 if ((type->eTypeClass == TypeClass.STRUCT ||
1687 type->eTypeClass == TypeClass.EXCEPTION) &&
1688 (type->nSize > sizeof(largest)))
1690 // stackalloc is only allowed in initializers
1691 byte *bigArgPtr = stackalloc byte[type->nSize];
1693 unoArgPtrs[i] = bigArgPtr;
1696 if (parameters[i].bIn != 0)
1698 // FIXME error handling
1699 MapToUno(unoArgPtrs[i], args[i], type, false /* no assign */);
1703 uno.Binary.Any unoExceptionHolder;
1704 uno.Binary.Any *unoExc = &unoExceptionHolder;
1706 // call binary uno
1707 uno.Binary.Interface.Dispatch(
1708 unoInterface, memberTD, unoRetPtr, unoArgPtrs, &unoExc);
1710 if (unoExc == null)
1712 exception = uno.Any.VOID;
1714 // convert out args, destroy uno args
1715 for (int i = 0; i < nParams; ++i)
1717 // FIXME it's a TypeDescriptionReference
1718 TypeDescription *type = (TypeDescription *)parameters[i].pTypeRef;
1720 if (parameters[i].bOut != 0)
1722 // FIXME error handling
1723 MapToManaged(ref args[i], unoArgPtrs[i], parameters[i].pTypeRef,
1724 argTypes != null ? argTypes[i] : null, false);
1727 // cleanup args
1728 if (type->eTypeClass < TypeClass.DOUBLE &&
1729 type->eTypeClass != TypeClass.ENUM) // no need to destroy these
1730 uno.Binary.Data.Destroy(unoArgPtrs[i], type, null);
1733 if (returnType != null && returnType->eTypeClass != TypeClass.VOID)
1735 // convert uno return value
1736 object result = null;
1737 // FIXME error handling
1738 MapToManaged(ref result, unoRetPtr, returnType, null, false);
1739 uno.Binary.Data.Destroy(unoRetPtr, (TypeDescription *)returnType, null);
1740 return new uno.Any(MapUnoType(returnType), result); // FIXME is this correct?
1743 return uno.Any.VOID;
1745 else // exception occured
1747 for (int i = 0; i < nParams; ++i)
1748 if (parameters[i].bIn != 0)
1749 uno.Binary.Data.Destroy(unoArgPtrs[i], (TypeDescription *)parameters[i].pTypeRef, null);
1751 // FIXME needs uno.Any vs System.Object clarification
1752 object exc = null;
1753 MapToManaged(ref exc, unoExceptionHolder.pData,
1754 unoExceptionHolder.pType, null, false);
1755 exception = new uno.Any(MapUnoType(unoExceptionHolder.pType), exc);
1756 return uno.Any.VOID;
1759 // FIXME error handling
1762 // FIXME rename, to say what it does, not how it does this
1763 public void RegisterWithCliEnvironment(object managedI, string oid)
1765 managedEnvironment.registerInterface(managedI, oid);
1768 public void RegisterWithCliEnvironment(object managedI, string oid, Type type)
1770 managedEnvironment.registerInterface(managedI, oid, type);
1773 public void RegisterWithUnoEnvironment(ref IntPtr unoInterface, string oid, InterfaceTypeDescription *TD)
1775 UString *unoOid = null;
1776 UString.NewFromString(&unoOid, oid);
1778 uno.Binary.Environment.RegisterInterface(unoEnvironment, ref unoInterface, unoOid, TD);
1780 UString.Release(unoOid);
1783 public void GetInterfaceFromUnoEnvironment(ref IntPtr unoInterface, UString* unoOid, InterfaceTypeDescription* TD)
1785 uno.Binary.Environment.GetRegisteredInterface(unoEnvironment, ref unoInterface, unoOid, TD);
1788 public void RevokeFromUnoEnvironment(IntPtr unoInterface)
1790 throw new NotImplementedException();
1793 public unsafe IntPtr CreateManagedProxy(object managedInterface,
1794 TypeDescription* td,
1795 UString* oid)
1797 // register original interface
1798 RegisterWithCliEnvironment(managedInterface,
1799 UString.UStringToString(oid),
1800 Bridge.MapUnoType(td));
1802 ManagedProxy proxy = new ManagedProxy(this, managedInterface, td, oid);
1803 GCHandle gchandle = GCHandle.Alloc(proxy);
1805 // create binary uno uno_Interface and register proxy with target environment
1806 IntPtr unoI = CreateBinaryProxyAndRegister(unoEnvironment, (IntPtr)gchandle,
1807 oid, td);
1809 proxy.NativeProxy = unoI;
1810 return unoI;
1813 [ DllImport("cli_uno", EntryPoint="cli_uno_environment_createMonoProxyAndRegister") ]
1814 public static unsafe extern IntPtr CreateBinaryProxyAndRegister(
1815 IntPtr unoEnvironment,
1816 IntPtr monoProxy,
1817 /* UString */ void* oid,
1818 /* InterfaceTypeDescription */ void* td);
1820 public unsafe void CallManaged(object managedI, Type ifaceType, MethodInfo method,
1821 TypeDescriptionReference* returnType,
1822 MethodParameter* parameters, int nParams, void* unoRet,
1823 void** unoArgs, uno.Binary.Any** unoExc)
1825 object[] args = new object[nParams];
1826 for (int i = 0; i < nParams; ++i)
1827 if (parameters[i].bIn != 0)
1828 MapToManaged(ref args[i], unoArgs[i], parameters[i].pTypeRef, null, false);
1830 object invocationResult = null;
1833 invocationResult = method.Invoke(managedI, args);
1835 catch (TargetInvocationException e)
1837 Exception exc = e.InnerException;
1838 TypeDescription* td = null;
1839 // FIXME leak
1840 TypeDescriptionReference.GetDescription(&td, MapManagedType(exc.GetType()));
1841 void* memExc = uno.rtl.Mem.Allocate(td->nSize);
1842 MapToUno(memExc, exc, /* FIXME !!!*/ (TypeDescription*)td->pWeakRef, false);
1843 (*unoExc)->pType = td->pWeakRef;
1844 (*unoExc)->pData = memExc;
1845 return;
1847 catch (Exception e)
1849 // FIXME
1852 // convert out, in/out params
1853 for (int i = 0; i < nParams; ++i)
1855 if (parameters[i].bOut != 0)
1857 MapToUno(
1858 unoArgs[i], args[i], /* FIXME !!! */(TypeDescription*)parameters[i].pTypeRef,
1859 parameters[i].bIn != 0 /* assign if inout */);
1860 // FIXME error handling
1864 // return value
1865 if (returnType != null)
1866 MapToUno(unoRet, invocationResult, /* FIXME !!! */(TypeDescription*)returnType, false /* no assign */);
1868 // no exception occurred
1869 *unoExc = null;