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 .
21 #include <sal/alloca.h>
22 #include <osl/diagnose.h>
23 #include "rtl/ustrbuf.hxx"
25 #include "cli_bridge.h"
27 namespace sr
=System::Reflection
;
41 System::Object
^ Bridge::call_uno(uno_Interface
* pUnoI
,
42 typelib_TypeDescription
* member_td
,
43 typelib_TypeDescriptionReference
* return_type
,
44 sal_Int32 nParams
, typelib_MethodParameter
const * pParams
,
45 array
<System::Object
^>^ args
, array
<System::Type
^>^ argTypes
,
46 System::Object
^* ppExc
) const
49 sal_Int32 return_size
= sizeof (largest
);
50 if ((0 != return_type
) &&
51 (typelib_TypeClass_STRUCT
== return_type
->eTypeClass
||
52 typelib_TypeClass_EXCEPTION
== return_type
->eTypeClass
))
54 TypeDescr
return_td( return_type
);
55 if (return_td
.get()->nSize
> sizeof (largest
))
56 return_size
= return_td
.get()->nSize
;
58 //Prepare memory that contains all converted arguments and return value
59 //The memory block contains first pointers to the arguments which are in the same block
60 // For example, 2 arguments, 1 ret.
68 // If an argument is larger then union largest, such as some structures, then the pointer
69 // points to an extra block of memory. The same goes for a big return value.
71 char * mem
= (char *)alloca(
72 (nParams
* sizeof (void *)) + return_size
+ (nParams
* sizeof (largest
)) );
73 //array of pointers to args
74 void ** uno_args
= (void **)mem
;
75 //If an attribute is set, then uno_ret must be null, e.g void setAttribute(int )
77 if ( !(member_td
->eTypeClass
== typelib_TypeClass_INTERFACE_ATTRIBUTE
&& nParams
== 1))
78 uno_ret
= (mem
+ (nParams
* sizeof (void *)));
79 largest
* uno_args_mem
= (largest
*)(mem
+ (nParams
* sizeof (void *)) + return_size
);
81 OSL_ASSERT( (0 == nParams
) || (nParams
== args
->Length
) );
82 for ( sal_Int32 nPos
= 0; nPos
< nParams
; ++nPos
)
84 typelib_MethodParameter
const & param
= pParams
[ nPos
];
85 typelib_TypeDescriptionReference
* type
= param
.pTypeRef
;
87 uno_args
[ nPos
] = &uno_args_mem
[ nPos
];
88 if (typelib_TypeClass_STRUCT
== type
->eTypeClass
||
89 typelib_TypeClass_EXCEPTION
== type
->eTypeClass
)
92 if (td
.get()->nSize
> sizeof (largest
))
93 uno_args
[ nPos
] = alloca( td
.get()->nSize
);
102 uno_args
[ nPos
],args
[nPos
] , type
, false /* no assign */);
106 // cleanup uno in args
107 for (sal_Int32 n
= 0; n
< nPos
; ++n
)
109 typelib_MethodParameter
const & param
= pParams
[n
];
112 uno_type_destructData(uno_args
[n
], param
.pTypeRef
, 0);
119 uno_Any uno_exc_holder
;
120 uno_Any
* uno_exc
= &uno_exc_holder
;
123 (*pUnoI
->pDispatcher
)( pUnoI
, member_td
, uno_ret
, uno_args
, &uno_exc
);
127 // convert out args; destruct uno args
128 for ( sal_Int32 nPos
= 0; nPos
< nParams
; ++nPos
)
130 typelib_MethodParameter
const & param
= pParams
[ nPos
];
131 typelib_TypeDescriptionReference
* type
= param
.pTypeRef
;
136 pin_ptr
<System::Object
^> ptr
= &args
[nPos
];
138 ptr
, uno_args
[nPos
], param
.pTypeRef
,
139 argTypes
!= nullptr ? argTypes
[nPos
] : nullptr, false );
143 // cleanup further uno args
144 for ( sal_Int32 n
= nPos
; n
< nParams
; ++n
)
146 uno_type_destructData( uno_args
[n
], pParams
[n
].pTypeRef
, 0 );
148 // cleanup uno return value
149 uno_type_destructData( uno_ret
, return_type
, 0 );
154 if (typelib_TypeClass_DOUBLE
< type
->eTypeClass
&&
155 typelib_TypeClass_ENUM
!= type
->eTypeClass
) // opt
157 uno_type_destructData(uno_args
[nPos
], type
, 0);
161 if ((0 != return_type
) &&
162 (typelib_TypeClass_VOID
!= return_type
->eTypeClass
))
164 // convert uno return value
167 System::Object
^ cli_ret
;
169 &cli_ret
, uno_ret
, return_type
, nullptr, false);
170 uno_type_destructData(uno_ret
, return_type
, 0);
175 uno_type_destructData(uno_ret
, return_type
, 0);
179 return nullptr; // void return
181 else // exception occurred
183 // destruct uno in args
184 for ( sal_Int32 nPos
= 0; nPos
< nParams
; ++nPos
)
186 typelib_MethodParameter
const & param
= pParams
[ nPos
];
189 uno_type_destructData( uno_args
[ nPos
], param
.pTypeRef
, 0 );
192 map_to_cli(ppExc
, uno_exc_holder
.pData
,
193 uno_exc_holder
.pType
, nullptr, false);
198 void Bridge::call_cli(
199 System::Object
^ cliI
,
200 sr::MethodInfo
^ method
,
201 typelib_TypeDescriptionReference
* return_type
,
202 typelib_MethodParameter
* params
, int nParams
,
203 void * uno_ret
, void * uno_args
[], uno_Any
** uno_exc
) const
205 array
<System::Object
^>^ args
= gcnew array
<System::Object
^>(nParams
);
206 for (int nPos
= 0; nPos
< nParams
; nPos
++)
208 typelib_MethodParameter
const & param
= params
[nPos
];
211 pin_ptr
<System::Object
^> ptr
= &args
[nPos
];
213 uno_args
[nPos
], param
.pTypeRef
, nullptr, false);
216 System::Object
^ retInvoke
= nullptr;
219 retInvoke
= method
->Invoke(cliI
, args
);
221 catch (sr::TargetInvocationException
^ e
)
223 System::Exception
^ exc
= e
->InnerException
;
224 css::uno::TypeDescription
td(mapCliType(exc
->GetType()));
225 // memory for exception
226 std::unique_ptr
< rtl_mem
> memExc(rtl_mem::allocate(td
.get()->nSize
));
227 map_to_uno(memExc
.get(), exc
, td
.get()->pWeakRef
, false);
228 (*uno_exc
)->pType
= td
.get()->pWeakRef
;
229 (*uno_exc
)->pData
= memExc
.release();
232 catch (System::Exception
^ e
)
234 throw BridgeRuntimeError("Unexpected exception during invocation of cli object. Original message is: \n" + mapCliString(e
->Message
));
237 //convert out, in/out params
238 for (int nPos
= 0; nPos
< nParams
; ++nPos
)
240 typelib_MethodParameter
const & param
= params
[ nPos
];
247 uno_args
[ nPos
], args
[ nPos
], param
.pTypeRef
,
248 sal_True
== param
.bIn
/* assign if inout */);
253 // cleanup uno pure out
254 for ( sal_Int32 n
= 0; n
< nPos
; ++n
)
256 typelib_MethodParameter
const & param
= params
[ n
];
258 uno_type_destructData( uno_args
[ n
], param
.pTypeRef
, 0 );
265 if (0 != return_type
)
268 uno_ret
, retInvoke
, return_type
, false /* no assign */);
270 // no exception occurred
277 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */