1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_cli_ure.hxx"
31 #include <sal/alloca.h>
32 #include "rtl/ustrbuf.hxx"
34 #include "cli_bridge.h"
36 namespace sr
=System::Reflection
;
37 namespace css
=com::sun::star
;
51 System::Object
* Bridge::call_uno(uno_Interface
* pUnoI
,
52 typelib_TypeDescription
* member_td
,
53 typelib_TypeDescriptionReference
* return_type
,
54 sal_Int32 nParams
, typelib_MethodParameter
const * pParams
,
55 System::Object
* args
[], System::Type
* argTypes
[],
56 System::Object
** ppExc
) const
59 sal_Int32 return_size
= sizeof (largest
);
60 if ((0 != return_type
) &&
61 (typelib_TypeClass_STRUCT
== return_type
->eTypeClass
||
62 typelib_TypeClass_EXCEPTION
== return_type
->eTypeClass
))
64 TypeDescr
return_td( return_type
);
65 if (return_td
.get()->nSize
> sizeof (largest
))
66 return_size
= return_td
.get()->nSize
;
68 //Prepare memory that contains all converted arguments and return valuse
69 //The memory block contains first pointers to the arguments which are in the same block
70 // For example, 2 arguments, 1 ret.
78 // If an argument is larger then union largest, such as some structures, then the pointer
79 // points to an extra block of memory. The same goes for a big return value.
81 char * mem
= (char *)alloca(
82 (nParams
* sizeof (void *)) + return_size
+ (nParams
* sizeof (largest
)) );
83 //array of pointers to args
84 void ** uno_args
= (void **)mem
;
85 //If an attribute is set, then uno_ret must be null, e.g void setAttribute(int )
87 if ( !(member_td
->eTypeClass
== typelib_TypeClass_INTERFACE_ATTRIBUTE
&& nParams
== 1))
88 uno_ret
= (mem
+ (nParams
* sizeof (void *)));
89 largest
* uno_args_mem
= (largest
*)(mem
+ (nParams
* sizeof (void *)) + return_size
);
91 OSL_ASSERT( (0 == nParams
) || (nParams
== args
->get_Length()) );
92 for ( sal_Int32 nPos
= 0; nPos
< nParams
; ++nPos
)
94 typelib_MethodParameter
const & param
= pParams
[ nPos
];
95 typelib_TypeDescriptionReference
* type
= param
.pTypeRef
;
97 uno_args
[ nPos
] = &uno_args_mem
[ nPos
];
98 if (typelib_TypeClass_STRUCT
== type
->eTypeClass
||
99 typelib_TypeClass_EXCEPTION
== type
->eTypeClass
)
101 TypeDescr
td( type
);
102 if (td
.get()->nSize
> sizeof (largest
))
103 uno_args
[ nPos
] = alloca( td
.get()->nSize
);
112 uno_args
[ nPos
],args
[nPos
] , type
, false /* no assign */);
116 // cleanup uno in args
117 for (sal_Int32 n
= 0; n
< nPos
; ++n
)
119 typelib_MethodParameter
const & param
= pParams
[n
];
122 uno_type_destructData(uno_args
[n
], param
.pTypeRef
, 0);
129 uno_Any uno_exc_holder
;
130 uno_Any
* uno_exc
= &uno_exc_holder
;
133 (*pUnoI
->pDispatcher
)( pUnoI
, member_td
, uno_ret
, uno_args
, &uno_exc
);
137 // convert out args; destruct uno args
138 for ( sal_Int32 nPos
= 0; nPos
< nParams
; ++nPos
)
140 typelib_MethodParameter
const & param
= pParams
[ nPos
];
141 typelib_TypeDescriptionReference
* type
= param
.pTypeRef
;
147 &args
[nPos
], uno_args
[nPos
], param
.pTypeRef
,
148 argTypes
!= NULL
? argTypes
[nPos
] : NULL
, false );
152 // cleanup further uno args
153 for ( sal_Int32 n
= nPos
; n
< nParams
; ++n
)
155 uno_type_destructData( uno_args
[n
], pParams
[n
].pTypeRef
, 0 );
157 // cleanup uno return value
158 uno_type_destructData( uno_ret
, return_type
, 0 );
163 if (typelib_TypeClass_DOUBLE
< type
->eTypeClass
&&
164 typelib_TypeClass_ENUM
!= type
->eTypeClass
) // opt
166 uno_type_destructData(uno_args
[nPos
], type
, 0);
170 if ((0 != return_type
) &&
171 (typelib_TypeClass_VOID
!= return_type
->eTypeClass
))
173 // convert uno return value
176 System::Object
* cli_ret
;
178 &cli_ret
, uno_ret
, return_type
, 0, false);
179 uno_type_destructData(uno_ret
, return_type
, 0);
184 uno_type_destructData(uno_ret
, return_type
, 0);
188 return 0; // void return
190 else // exception occured
192 // destruct uno in args
193 for ( sal_Int32 nPos
= 0; nPos
< nParams
; ++nPos
)
195 typelib_MethodParameter
const & param
= pParams
[ nPos
];
198 uno_type_destructData( uno_args
[ nPos
], param
.pTypeRef
, 0 );
201 map_to_cli(ppExc
, uno_exc_holder
.pData
,
202 uno_exc_holder
.pType
, NULL
, false);
207 void Bridge::call_cli(
208 System::Object
* cliI
,
209 sr::MethodInfo
* method
,
210 typelib_TypeDescriptionReference
* return_type
,
211 typelib_MethodParameter
* params
, int nParams
,
212 void * uno_ret
, void * uno_args
[], uno_Any
** uno_exc
) const
214 System::Object
*args
[]= new System::Object
*[nParams
];
215 for (int nPos
= 0; nPos
< nParams
; nPos
++)
217 typelib_MethodParameter
const & param
= params
[nPos
];
220 map_to_cli( &args
[nPos
],
221 uno_args
[nPos
], param
.pTypeRef
, 0, false);
224 System::Object
* retInvoke
= NULL
;
227 retInvoke
= method
->Invoke(cliI
, args
);
229 catch (sr::TargetInvocationException
* e
)
231 System::Exception
* exc
= e
->get_InnerException();
232 css::uno::TypeDescription
td(mapCliType(exc
->GetType()));
233 // memory for exception
234 std::auto_ptr
< rtl_mem
> memExc(rtl_mem::allocate(td
.get()->nSize
));
235 map_to_uno(memExc
.get(), exc
, td
.get()->pWeakRef
, false);
236 (*uno_exc
)->pType
= td
.get()->pWeakRef
;
237 (*uno_exc
)->pData
= memExc
.release();
240 catch (System::Exception
* e
)
242 OUStringBuffer
buf( 128 );
243 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM(
244 "Unexspected exception during invocation of cli object. "
245 "Original message is: \n") );
246 buf
.append(mapCliString(e
->get_Message()));
247 throw BridgeRuntimeError( buf
.makeStringAndClear() );
250 //convert out, in/out params
251 for (int nPos
= 0; nPos
< nParams
; ++nPos
)
253 typelib_MethodParameter
const & param
= params
[ nPos
];
260 uno_args
[ nPos
], args
[ nPos
], param
.pTypeRef
,
261 sal_True
== param
.bIn
/* assign if inout */);
266 // cleanup uno pure out
267 for ( sal_Int32 n
= 0; n
< nPos
; ++n
)
269 typelib_MethodParameter
const & param
= params
[ n
];
271 uno_type_destructData( uno_args
[ n
], param
.pTypeRef
, 0 );
278 if (0 != return_type
)
281 uno_ret
, retInvoke
, return_type
, false /* no assign */);
283 // no exception occured