1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/alloca.h>
21 #include "rtl/ustrbuf.hxx"
23 #include "cli_bridge.h"
25 namespace sr
=System::Reflection
;
39 System::Object
^ Bridge::call_uno(uno_Interface
* pUnoI
,
40 typelib_TypeDescription
* member_td
,
41 typelib_TypeDescriptionReference
* return_type
,
42 sal_Int32 nParams
, typelib_MethodParameter
const * pParams
,
43 array
<System::Object
^>^ args
, array
<System::Type
^>^ argTypes
,
44 System::Object
^* ppExc
) const
47 sal_Int32 return_size
= sizeof (largest
);
48 if ((0 != return_type
) &&
49 (typelib_TypeClass_STRUCT
== return_type
->eTypeClass
||
50 typelib_TypeClass_EXCEPTION
== return_type
->eTypeClass
))
52 TypeDescr
return_td( return_type
);
53 if (return_td
.get()->nSize
> sizeof (largest
))
54 return_size
= return_td
.get()->nSize
;
56 //Prepare memory that contains all converted arguments and return valuse
57 //The memory block contains first pointers to the arguments which are in the same block
58 // For example, 2 arguments, 1 ret.
66 // If an argument is larger then union largest, such as some structures, then the pointer
67 // points to an extra block of memory. The same goes for a big return value.
69 char * mem
= (char *)alloca(
70 (nParams
* sizeof (void *)) + return_size
+ (nParams
* sizeof (largest
)) );
71 //array of pointers to args
72 void ** uno_args
= (void **)mem
;
73 //If an attribute is set, then uno_ret must be null, e.g void setAttribute(int )
75 if ( !(member_td
->eTypeClass
== typelib_TypeClass_INTERFACE_ATTRIBUTE
&& nParams
== 1))
76 uno_ret
= (mem
+ (nParams
* sizeof (void *)));
77 largest
* uno_args_mem
= (largest
*)(mem
+ (nParams
* sizeof (void *)) + return_size
);
79 OSL_ASSERT( (0 == nParams
) || (nParams
== args
->Length
) );
80 for ( sal_Int32 nPos
= 0; nPos
< nParams
; ++nPos
)
82 typelib_MethodParameter
const & param
= pParams
[ nPos
];
83 typelib_TypeDescriptionReference
* type
= param
.pTypeRef
;
85 uno_args
[ nPos
] = &uno_args_mem
[ nPos
];
86 if (typelib_TypeClass_STRUCT
== type
->eTypeClass
||
87 typelib_TypeClass_EXCEPTION
== type
->eTypeClass
)
90 if (td
.get()->nSize
> sizeof (largest
))
91 uno_args
[ nPos
] = alloca( td
.get()->nSize
);
100 uno_args
[ nPos
],args
[nPos
] , type
, false /* no assign */);
104 // cleanup uno in args
105 for (sal_Int32 n
= 0; n
< nPos
; ++n
)
107 typelib_MethodParameter
const & param
= pParams
[n
];
110 uno_type_destructData(uno_args
[n
], param
.pTypeRef
, 0);
117 uno_Any uno_exc_holder
;
118 uno_Any
* uno_exc
= &uno_exc_holder
;
121 (*pUnoI
->pDispatcher
)( pUnoI
, member_td
, uno_ret
, uno_args
, &uno_exc
);
125 // convert out args; destruct uno args
126 for ( sal_Int32 nPos
= 0; nPos
< nParams
; ++nPos
)
128 typelib_MethodParameter
const & param
= pParams
[ nPos
];
129 typelib_TypeDescriptionReference
* type
= param
.pTypeRef
;
134 pin_ptr
<System::Object
^> ptr
= &args
[nPos
];
136 ptr
, uno_args
[nPos
], param
.pTypeRef
,
137 argTypes
!= nullptr ? argTypes
[nPos
] : nullptr, false );
141 // cleanup further uno args
142 for ( sal_Int32 n
= nPos
; n
< nParams
; ++n
)
144 uno_type_destructData( uno_args
[n
], pParams
[n
].pTypeRef
, 0 );
146 // cleanup uno return value
147 uno_type_destructData( uno_ret
, return_type
, 0 );
152 if (typelib_TypeClass_DOUBLE
< type
->eTypeClass
&&
153 typelib_TypeClass_ENUM
!= type
->eTypeClass
) // opt
155 uno_type_destructData(uno_args
[nPos
], type
, 0);
159 if ((0 != return_type
) &&
160 (typelib_TypeClass_VOID
!= return_type
->eTypeClass
))
162 // convert uno return value
165 System::Object
^ cli_ret
;
167 &cli_ret
, uno_ret
, return_type
, nullptr, false);
168 uno_type_destructData(uno_ret
, return_type
, 0);
173 uno_type_destructData(uno_ret
, return_type
, 0);
177 return nullptr; // void return
179 else // exception occurred
181 // destruct uno in args
182 for ( sal_Int32 nPos
= 0; nPos
< nParams
; ++nPos
)
184 typelib_MethodParameter
const & param
= pParams
[ nPos
];
187 uno_type_destructData( uno_args
[ nPos
], param
.pTypeRef
, 0 );
190 map_to_cli(ppExc
, uno_exc_holder
.pData
,
191 uno_exc_holder
.pType
, nullptr, false);
196 void Bridge::call_cli(
197 System::Object
^ cliI
,
198 sr::MethodInfo
^ method
,
199 typelib_TypeDescriptionReference
* return_type
,
200 typelib_MethodParameter
* params
, int nParams
,
201 void * uno_ret
, void * uno_args
[], uno_Any
** uno_exc
) const
203 array
<System::Object
^>^ args
= gcnew array
<System::Object
^>(nParams
);
204 for (int nPos
= 0; nPos
< nParams
; nPos
++)
206 typelib_MethodParameter
const & param
= params
[nPos
];
209 pin_ptr
<System::Object
^> ptr
= &args
[nPos
];
211 uno_args
[nPos
], param
.pTypeRef
, nullptr, false);
214 System::Object
^ retInvoke
= nullptr;
217 retInvoke
= method
->Invoke(cliI
, args
);
219 catch (sr::TargetInvocationException
^ e
)
221 System::Exception
^ exc
= e
->InnerException
;
222 css::uno::TypeDescription
td(mapCliType(exc
->GetType()));
223 // memory for exception
224 std::auto_ptr
< rtl_mem
> memExc(rtl_mem::allocate(td
.get()->nSize
));
225 map_to_uno(memExc
.get(), exc
, td
.get()->pWeakRef
, false);
226 (*uno_exc
)->pType
= td
.get()->pWeakRef
;
227 (*uno_exc
)->pData
= memExc
.release();
230 catch (System::Exception
^ e
)
232 OUStringBuffer
buf( 128 );
233 buf
.append( "Unexpected exception during invocation of cli object. "
234 "Original message is: \n" );
235 buf
.append(mapCliString(e
->Message
));
236 throw BridgeRuntimeError( buf
.makeStringAndClear() );
239 //convert out, in/out params
240 for (int nPos
= 0; nPos
< nParams
; ++nPos
)
242 typelib_MethodParameter
const & param
= params
[ nPos
];
249 uno_args
[ nPos
], args
[ nPos
], param
.pTypeRef
,
250 sal_True
== param
.bIn
/* assign if inout */);
255 // cleanup uno pure out
256 for ( sal_Int32 n
= 0; n
< nPos
; ++n
)
258 typelib_MethodParameter
const & param
= params
[ n
];
260 uno_type_destructData( uno_args
[ n
], param
.pTypeRef
, 0 );
267 if (0 != return_type
)
270 uno_ret
, retInvoke
, return_type
, false /* no assign */);
272 // no exception occurred
281 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */