LibreOffice Module cli_ure (master) 1
cli_uno.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
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"
26
27namespace sr=System::Reflection;
28
29
30namespace cli_uno
31{
32
34{
35 sal_Int64 n;
36 double d;
37 void * p;
39};
40
41System::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
47{
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))
53 {
54 TypeDescr return_td( return_type );
55 if (return_td.get()->nSize > sizeof (largest))
56 return_size = return_td.get()->nSize;
57 }
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.
61 //
62 // | Pointer
63 // | Pointer
64 // | Return value
65 // | Arg 1
66 // | Arg 2
67 //
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.
70
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);
80
81 OSL_ASSERT( (0 == nParams) || (nParams == args->Length) );
82 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
83 {
84 typelib_MethodParameter const & param = pParams[ nPos ];
85 typelib_TypeDescriptionReference * type = param.pTypeRef;
86
87 uno_args[ nPos ] = &uno_args_mem[ nPos ];
88 if (typelib_TypeClass_STRUCT == type->eTypeClass ||
89 typelib_TypeClass_EXCEPTION == type->eTypeClass)
90 {
91 TypeDescr td( type );
92 if (td.get()->nSize > sizeof (largest))
93 uno_args[ nPos ] = alloca( td.get()->nSize );
94 }
95
96 if (param.bIn)
97 {
98 try
99 {
100 // in, in/out params
102 uno_args[ nPos ],args[nPos] , type, false /* no assign */);
103 }
104 catch (...)
105 {
106 // cleanup uno in args
107 for (sal_Int32 n = 0; n < nPos; ++n)
108 {
109 typelib_MethodParameter const & param = pParams[n];
110 if (param.bIn)
111 {
112 uno_type_destructData(uno_args[n], param.pTypeRef, 0);
113 }
114 }
115 throw;
116 }
117 }
118 }
119 uno_Any uno_exc_holder;
120 uno_Any * uno_exc = &uno_exc_holder;
121 // call binary uno
122
123 (*pUnoI->pDispatcher)( pUnoI, member_td, uno_ret, uno_args, &uno_exc );
124
125 if (0 == uno_exc)
126 {
127 // convert out args; destruct uno args
128 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
129 {
130 typelib_MethodParameter const & param = pParams[ nPos ];
131 typelib_TypeDescriptionReference * type = param.pTypeRef;
132 if (param.bOut)
133 {
134 try
135 {
136 pin_ptr<System::Object^> ptr = &args[nPos];
138 ptr, uno_args[nPos], param.pTypeRef,
139 argTypes != nullptr ? argTypes[nPos] : nullptr, false );
140 }
141 catch (...)
142 {
143 // cleanup further uno args
144 for ( sal_Int32 n = nPos; n < nParams; ++n )
145 {
146 uno_type_destructData( uno_args[n], pParams[n].pTypeRef, 0 );
147 }
148 // cleanup uno return value
149 uno_type_destructData( uno_ret, return_type, 0 );
150 throw;
151 }
152 }
153 //cleanup args
154 if (typelib_TypeClass_DOUBLE < type->eTypeClass &&
155 typelib_TypeClass_ENUM != type->eTypeClass) // opt
156 {
157 uno_type_destructData(uno_args[nPos], type, 0);
158 }
159 }
160
161 if ((0 != return_type) &&
162 (typelib_TypeClass_VOID != return_type->eTypeClass))
163 {
164 // convert uno return value
165 try
166 {
167 System::Object^ cli_ret;
169 &cli_ret, uno_ret, return_type, nullptr, false);
170 uno_type_destructData(uno_ret, return_type, 0);
171 return cli_ret;
172 }
173 catch (...)
174 {
175 uno_type_destructData(uno_ret, return_type, 0);
176 throw;
177 }
178 }
179 return nullptr; // void return
180 }
181 else // exception occurred
182 {
183 // destruct uno in args
184 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
185 {
186 typelib_MethodParameter const & param = pParams[ nPos ];
187 if (param.bIn)
188 {
189 uno_type_destructData( uno_args[ nPos ], param.pTypeRef, 0 );
190 }
191 }
192 map_to_cli(ppExc, uno_exc_holder.pData,
193 uno_exc_holder.pType, nullptr, false);
194 return nullptr;
195 }
196}
197
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
204{
205 array<System::Object^>^ args= gcnew array<System::Object^>(nParams);
206 for (int nPos= 0; nPos < nParams; nPos++)
207 {
208 typelib_MethodParameter const & param= params[nPos];
209 if (param.bIn)
210 {
211 pin_ptr<System::Object^> ptr = &args[nPos];
212 map_to_cli( ptr,
213 uno_args[nPos], param.pTypeRef, nullptr, false);
214 }
215 }
216 System::Object^ retInvoke= nullptr;
217 try
218 {
219 retInvoke= method->Invoke(cliI, args);
220 }
221 catch (sr::TargetInvocationException^ e)
222 {
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;
231 }
232 catch (System::Exception^ e)
233 {
234 throw BridgeRuntimeError("Unexpected exception during invocation of cli object. Original message is: \n" + mapCliString(e->Message));
235 }
236
237 //convert out, in/out params
238 for (int nPos = 0; nPos < nParams; ++nPos )
239 {
240 typelib_MethodParameter const & param = params[ nPos ];
241
242 if (param.bOut)
243 {
244 try
245 {
247 uno_args[ nPos ], args[ nPos ], param.pTypeRef,
248 sal_True == param.bIn /* assign if inout */);
249 // out array
250 }
251 catch (...)
252 {
253 // cleanup uno pure out
254 for ( sal_Int32 n = 0; n < nPos; ++n )
255 {
256 typelib_MethodParameter const & param = params[ n ];
257 if (! param.bIn)
258 uno_type_destructData( uno_args[ n ], param.pTypeRef, 0 );
259 }
260 throw;
261 }
262 }
263 }
264 // return value
265 if (0 != return_type)
266 {
268 uno_ret, retInvoke, return_type, false /* no assign */);
269 }
270 // no exception occurred
271 *uno_exc = 0;
272}
273
274
275}
276
277/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
typelib_TypeDescription * get() const
Definition: cli_base.h:151
void SAL_CALL uno_type_destructData(void *pValue, typelib_TypeDescriptionReference *pType, uno_ReleaseFunc release) SAL_THROW_EXTERN_C()
sal_Int64 n
sal_uInt16 nPos
return NULL
struct _typelib_TypeDescription typelib_TypeDescription
struct _uno_Any uno_Any
OUString mapCliString(System::String ^ data)
Definition: cli_data.cxx:715
typelib_TypeDescriptionReference * mapCliType(System::Type^ cliType)
Returns an acquired td.
Definition: cli_data.cxx:312
args
System::Object call_uno(uno_Interface *pUnoI, typelib_TypeDescription *member_td, typelib_TypeDescriptionReference *return_type, sal_Int32 nParams, typelib_MethodParameter const *pParams, array< System::Object^>^ args, array< System::Type^>^ argTypes, System::Object^ *pException) const
Definition: cli_uno.cxx:41
void map_to_uno(void *uno_data, System::Object^ cli_data, typelib_TypeDescriptionReference *type, bool assign) const
Definition: cli_data.cxx:735
void call_cli(System::Object^ cliI, sr::MethodInfo^ method, typelib_TypeDescriptionReference *return_type, typelib_MethodParameter *params, int nParams, void *uno_ret, void *uno_args[], uno_Any **uno_exc) const
Definition: cli_uno.cxx:198
void map_to_cli(System::Object^ *cli_data, void const *uno_data, typelib_TypeDescriptionReference *type, System::Type^ info, bool bDontCreateObj) const
Definition: cli_data.cxx:1448
static std::unique_ptr< rtl_mem > allocate(std::size_t bytes)
Definition: cli_base.h:130
#define sal_True
ResultType type
sal_Int64 n
Definition: cli_uno.cxx:35