Bump version to 24.04.3.4
[LibreOffice.git] / cli_ure / source / uno_bridge / cli_uno.cxx
blob6af17e065505be8bd1ed97bf5f3f516dfdb0a870
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <memory>
21 #include <sal/alloca.h>
22 #include <osl/diagnose.h>
23 #include "rtl/ustrbuf.hxx"
24 #include "cli_base.h"
25 #include "cli_bridge.h"
27 namespace sr=System::Reflection;
30 namespace cli_uno
33 union largest
35 sal_Int64 n;
36 double d;
37 void * p;
38 uno_Any a;
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
48 // return mem
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.
62 // | Pointer
63 // | Pointer
64 // | Return value
65 // | Arg 1
66 // | Arg 2
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 )
76 void * uno_ret= NULL;
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)
91 TypeDescr td( type );
92 if (td.get()->nSize > sizeof (largest))
93 uno_args[ nPos ] = alloca( td.get()->nSize );
96 if (param.bIn)
98 try
100 // in, in/out params
101 map_to_uno(
102 uno_args[ nPos ],args[nPos] , type, false /* no assign */);
104 catch (...)
106 // cleanup uno in args
107 for (sal_Int32 n = 0; n < nPos; ++n)
109 typelib_MethodParameter const & param = pParams[n];
110 if (param.bIn)
112 uno_type_destructData(uno_args[n], param.pTypeRef, 0);
115 throw;
119 uno_Any uno_exc_holder;
120 uno_Any * uno_exc = &uno_exc_holder;
121 // call binary uno
123 (*pUnoI->pDispatcher)( pUnoI, member_td, uno_ret, uno_args, &uno_exc );
125 if (0 == 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;
132 if (param.bOut)
136 pin_ptr<System::Object^> ptr = &args[nPos];
137 map_to_cli(
138 ptr, uno_args[nPos], param.pTypeRef,
139 argTypes != nullptr ? argTypes[nPos] : nullptr, false );
141 catch (...)
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 );
150 throw;
153 //cleanup args
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;
168 map_to_cli(
169 &cli_ret, uno_ret, return_type, nullptr, false);
170 uno_type_destructData(uno_ret, return_type, 0);
171 return cli_ret;
173 catch (...)
175 uno_type_destructData(uno_ret, return_type, 0);
176 throw;
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 ];
187 if (param.bIn)
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);
194 return nullptr;
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];
209 if (param.bIn)
211 pin_ptr<System::Object^> ptr = &args[nPos];
212 map_to_cli( ptr,
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();
230 return;
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 ];
242 if (param.bOut)
246 map_to_uno(
247 uno_args[ nPos ], args[ nPos ], param.pTypeRef,
248 sal_True == param.bIn /* assign if inout */);
249 // out array
251 catch (...)
253 // cleanup uno pure out
254 for ( sal_Int32 n = 0; n < nPos; ++n )
256 typelib_MethodParameter const & param = params[ n ];
257 if (! param.bIn)
258 uno_type_destructData( uno_args[ n ], param.pTypeRef, 0 );
260 throw;
264 // return value
265 if (0 != return_type)
267 map_to_uno(
268 uno_ret, retInvoke, return_type, false /* no assign */);
270 // no exception occurred
271 *uno_exc = 0;
277 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */