1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_cli_ure.hxx" 26 27 #include <sal/alloca.h> 28 #include "rtl/ustrbuf.hxx" 29 #include "cli_base.h" 30 #include "cli_bridge.h" 31 32 namespace sr=System::Reflection; 33 namespace css=com::sun::star; 34 using namespace rtl; 35 36 namespace cli_uno 37 { 38 39 union largest 40 { 41 sal_Int64 n; 42 double d; 43 void * p; 44 uno_Any a; 45 }; 46 47 System::Object* Bridge::call_uno(uno_Interface * pUnoI, 48 typelib_TypeDescription* member_td, 49 typelib_TypeDescriptionReference * return_type, 50 sal_Int32 nParams, typelib_MethodParameter const * pParams, 51 System::Object * args[], System::Type* argTypes[], 52 System::Object** ppExc) const 53 { 54 // return mem 55 sal_Int32 return_size = sizeof (largest); 56 if ((0 != return_type) && 57 (typelib_TypeClass_STRUCT == return_type->eTypeClass || 58 typelib_TypeClass_EXCEPTION == return_type->eTypeClass)) 59 { 60 TypeDescr return_td( return_type ); 61 if (return_td.get()->nSize > sizeof (largest)) 62 return_size = return_td.get()->nSize; 63 } 64 //Prepare memory that contains all converted arguments and return valuse 65 //The memory block contains first pointers to the arguments which are in the same block 66 // For example, 2 arguments, 1 ret. 67 // 68 // | Pointer 69 // | Pointer 70 // | Return value 71 // | Arg 1 72 // | Arg 2 73 // 74 // If an argument is larger then union largest, such as some structures, then the pointer 75 // points to an extra block of memory. The same goes for a big return value. 76 77 char * mem = (char *)alloca( 78 (nParams * sizeof (void *)) + return_size + (nParams * sizeof (largest)) ); 79 //array of pointers to args 80 void ** uno_args = (void **)mem; 81 //If an attribute is set, then uno_ret must be null, e.g void setAttribute(int ) 82 void * uno_ret= NULL; 83 if ( !(member_td->eTypeClass == typelib_TypeClass_INTERFACE_ATTRIBUTE && nParams == 1)) 84 uno_ret = (mem + (nParams * sizeof (void *))); 85 largest * uno_args_mem = (largest *)(mem + (nParams * sizeof (void *)) + return_size); 86 87 OSL_ASSERT( (0 == nParams) || (nParams == args->get_Length()) ); 88 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) 89 { 90 typelib_MethodParameter const & param = pParams[ nPos ]; 91 typelib_TypeDescriptionReference * type = param.pTypeRef; 92 93 uno_args[ nPos ] = &uno_args_mem[ nPos ]; 94 if (typelib_TypeClass_STRUCT == type->eTypeClass || 95 typelib_TypeClass_EXCEPTION == type->eTypeClass) 96 { 97 TypeDescr td( type ); 98 if (td.get()->nSize > sizeof (largest)) 99 uno_args[ nPos ] = alloca( td.get()->nSize ); 100 } 101 102 if (param.bIn) 103 { 104 try 105 { 106 // in, in/out params 107 map_to_uno( 108 uno_args[ nPos ],args[nPos] , type, false /* no assign */); 109 } 110 catch (...) 111 { 112 // cleanup uno in args 113 for (sal_Int32 n = 0; n < nPos; ++n) 114 { 115 typelib_MethodParameter const & param = pParams[n]; 116 if (param.bIn) 117 { 118 uno_type_destructData(uno_args[n], param.pTypeRef, 0); 119 } 120 } 121 throw; 122 } 123 } 124 } 125 uno_Any uno_exc_holder; 126 uno_Any * uno_exc = &uno_exc_holder; 127 // call binary uno 128 129 (*pUnoI->pDispatcher)( pUnoI, member_td, uno_ret, uno_args, &uno_exc ); 130 131 if (0 == uno_exc) 132 { 133 // convert out args; destruct uno args 134 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) 135 { 136 typelib_MethodParameter const & param = pParams[ nPos ]; 137 typelib_TypeDescriptionReference * type = param.pTypeRef; 138 if (param.bOut) 139 { 140 try 141 { 142 map_to_cli( 143 &args[nPos], uno_args[nPos], param.pTypeRef, 144 argTypes != NULL ? argTypes[nPos] : NULL, false ); 145 } 146 catch (...) 147 { 148 // cleanup further uno args 149 for ( sal_Int32 n = nPos; n < nParams; ++n ) 150 { 151 uno_type_destructData( uno_args[n], pParams[n].pTypeRef, 0 ); 152 } 153 // cleanup uno return value 154 uno_type_destructData( uno_ret, return_type, 0 ); 155 throw; 156 } 157 } 158 //cleanup args 159 if (typelib_TypeClass_DOUBLE < type->eTypeClass && 160 typelib_TypeClass_ENUM != type->eTypeClass) // opt 161 { 162 uno_type_destructData(uno_args[nPos], type, 0); 163 } 164 } 165 166 if ((0 != return_type) && 167 (typelib_TypeClass_VOID != return_type->eTypeClass)) 168 { 169 // convert uno return value 170 try 171 { 172 System::Object* cli_ret; 173 map_to_cli( 174 &cli_ret, uno_ret, return_type, 0, false); 175 uno_type_destructData(uno_ret, return_type, 0); 176 return cli_ret; 177 } 178 catch (...) 179 { 180 uno_type_destructData(uno_ret, return_type, 0); 181 throw; 182 } 183 } 184 return 0; // void return 185 } 186 else // exception occured 187 { 188 // destruct uno in args 189 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) 190 { 191 typelib_MethodParameter const & param = pParams[ nPos ]; 192 if (param.bIn) 193 { 194 uno_type_destructData( uno_args[ nPos ], param.pTypeRef, 0 ); 195 } 196 } 197 map_to_cli(ppExc, uno_exc_holder.pData, 198 uno_exc_holder.pType, NULL, false); 199 return 0; 200 } 201 } 202 203 void Bridge::call_cli( 204 System::Object* cliI, 205 sr::MethodInfo* method, 206 typelib_TypeDescriptionReference * return_type, 207 typelib_MethodParameter * params, int nParams, 208 void * uno_ret, void * uno_args [], uno_Any ** uno_exc ) const 209 { 210 System::Object *args[]= new System::Object*[nParams]; 211 for (int nPos= 0; nPos < nParams; nPos++) 212 { 213 typelib_MethodParameter const & param= params[nPos]; 214 if (param.bIn) 215 { 216 map_to_cli( &args[nPos], 217 uno_args[nPos], param.pTypeRef, 0, false); 218 } 219 } 220 System::Object* retInvoke= NULL; 221 try 222 { 223 retInvoke= method->Invoke(cliI, args); 224 } 225 catch (sr::TargetInvocationException* e) 226 { 227 System::Exception* exc= e->get_InnerException(); 228 css::uno::TypeDescription td(mapCliType(exc->GetType())); 229 // memory for exception 230 std::auto_ptr< rtl_mem > memExc(rtl_mem::allocate(td.get()->nSize)); 231 map_to_uno(memExc.get(), exc, td.get()->pWeakRef, false); 232 (*uno_exc)->pType= td.get()->pWeakRef; 233 (*uno_exc)->pData= memExc.release(); 234 return; 235 } 236 catch (System::Exception* e) 237 { 238 OUStringBuffer buf( 128 ); 239 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( 240 "Unexspected exception during invocation of cli object. " 241 "Original message is: \n") ); 242 buf.append(mapCliString(e->get_Message())); 243 throw BridgeRuntimeError( buf.makeStringAndClear() ); 244 } 245 246 //convert out, in/out params 247 for (int nPos = 0; nPos < nParams; ++nPos ) 248 { 249 typelib_MethodParameter const & param = params[ nPos ]; 250 251 if (param.bOut) 252 { 253 try 254 { 255 map_to_uno( 256 uno_args[ nPos ], args[ nPos ], param.pTypeRef, 257 sal_True == param.bIn /* assign if inout */); 258 // out array 259 } 260 catch (...) 261 { 262 // cleanup uno pure out 263 for ( sal_Int32 n = 0; n < nPos; ++n ) 264 { 265 typelib_MethodParameter const & param = params[ n ]; 266 if (! param.bIn) 267 uno_type_destructData( uno_args[ n ], param.pTypeRef, 0 ); 268 } 269 throw; 270 } 271 } 272 } 273 // return value 274 if (0 != return_type) 275 { 276 map_to_uno( 277 uno_ret, retInvoke, return_type, false /* no assign */); 278 } 279 // no exception occured 280 *uno_exc = 0; 281 } 282 283 284 285 286 } 287