/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
// see if the interface was already mapped
System::Type^ ifaceType= mapUnoType(reinterpret_cast<typelib_TypeDescription*>(pTD));
System::String^ sOid= mapUnoString(oid.pData);
System::Threading::Monitor::Enter( CliEnvHolder::g_cli_env ); try
{
retVal = CliEnvHolder::g_cli_env->getRegisteredInterface(sOid, ifaceType); if (retVal)
{ // There is already a registered object. It can either be a proxy // for the UNO object or a real cli object. In the first case we // tell the proxy that it shall also represent the current UNO // interface. If it already does that, then it does nothing if (srr::RemotingServices::IsTransparentProxy(retVal))
{
UnoInterfaceProxy^ p = static_cast<UnoInterfaceProxy^>(
srr::RemotingServices::GetRealProxy(retVal));
p->addUnoInterface(pUnoI, pTD);
}
} else
{
retVal = UnoInterfaceProxy::create(
(Bridge *) this, pUnoI, pTD, oid );
}
}
__finally
{
System::Threading::Monitor::Exit( CliEnvHolder::g_cli_env );
}
return retVal;
}
uno_Interface* Bridge::map_cli2uno(System::Object^ cliObj, typelib_TypeDescription *pTD) const
{
uno_Interface* retIface = NULL; // get oid from dot net environment
System::String^ ds_oid = CliEnvHolder::g_cli_env->getObjectIdentifier( cliObj);
OUString ousOid = mapCliString(ds_oid); // look if interface is already mapped
m_uno_env->getRegisteredInterface(m_uno_env, (void**) &retIface, ousOid.pData,
(typelib_InterfaceTypeDescription*) pTD); if ( ! retIface)
{
System::Threading::Monitor::Enter(Cli_environment::typeid); try
{
m_uno_env->getRegisteredInterface(m_uno_env, (void**) &retIface, ousOid.pData,
(typelib_InterfaceTypeDescription*) pTD); if ( ! retIface)
{
retIface = CliProxy::create((Bridge*)this, cliObj, pTD, ousOid);
}
}
__finally
{
System::Threading::Monitor::Exit(Cli_environment::typeid);
}
} return retIface;
}
System::Type^ loadCliType(System::String ^ unoName)
{
System::Type^ retVal= nullptr; try
{ //If unoName denotes a polymorphic type, e.g com.sun.star.beans.Defaulted<System.Char> //then we remove the type list, otherwise the type could not be loaded. bool bIsPolymorphic = false;
System::String ^ loadName = unoName; int index = unoName->IndexOf('<'); if (index != -1)
{
loadName = unoName->Substring(0, index);
bIsPolymorphic = true;
}
System::AppDomain^ currentDomain = System::AppDomain::CurrentDomain;
cli::array<sr::Assembly^>^ assems = currentDomain->GetAssemblies(); for (int i = 0; i < assems->Length; i++)
{
retVal = assems[i]->GetType(loadName, false); if (retVal) break;
}
if (retVal == nullptr)
{
System::String ^ msg = gcnew System::String("A type could not be loaded: ");
msg = System::String::Concat(msg, loadName); throw BridgeRuntimeError(mapCliString(msg));
}
System::Type^ mapUnoType(typelib_TypeDescriptionReference const * pTD)
{
System::Type ^ retVal = nullptr; switch (pTD->eTypeClass)
{ case typelib_TypeClass_VOID:
retVal= void::typeid; break; case typelib_TypeClass_CHAR:
retVal= System::Char::typeid; break; case typelib_TypeClass_BOOLEAN:
retVal= System::Boolean::typeid; break; case typelib_TypeClass_BYTE:
retVal= System::Byte::typeid; break; case typelib_TypeClass_SHORT:
retVal= System::Int16::typeid; break; case typelib_TypeClass_UNSIGNED_SHORT:
retVal= System::UInt16::typeid; break; case typelib_TypeClass_LONG:
retVal= System::Int32::typeid; break; case typelib_TypeClass_UNSIGNED_LONG:
retVal= System::UInt32::typeid; break; case typelib_TypeClass_HYPER:
retVal= System::Int64::typeid; break; case typelib_TypeClass_UNSIGNED_HYPER:
retVal= System::UInt64::typeid; break; case typelib_TypeClass_FLOAT:
retVal= System::Single::typeid; break; case typelib_TypeClass_DOUBLE:
retVal= System::Double::typeid; break; case typelib_TypeClass_STRING:
retVal= System::String::typeid; break; case typelib_TypeClass_TYPE:
retVal= System::Type::typeid; break; case typelib_TypeClass_ANY:
retVal= uno::Any::typeid; break; case typelib_TypeClass_ENUM: case typelib_TypeClass_STRUCT: case typelib_TypeClass_EXCEPTION:
retVal= loadCliType(pTD->pTypeName); break; case typelib_TypeClass_INTERFACE:
{ //special handling for XInterface, since it does not exist in cli.
OUString usXInterface("com.sun.star.uno.XInterface"); if (usXInterface.equals(pTD->pTypeName))
retVal= System::Object::typeid; else
retVal= loadCliType(pTD->pTypeName); break;
} case typelib_TypeClass_SEQUENCE:
{
css::uno::TypeDescription seqType( const_cast<typelib_TypeDescriptionReference*>(pTD));
typelib_TypeDescriptionReference* pElementTDRef= reinterpret_cast<typelib_IndirectTypeDescription*>(seqType.get())->pType; switch (pElementTDRef->eTypeClass)
{ case typelib_TypeClass_CHAR:
retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArChar)); break; case typelib_TypeClass_BOOLEAN:
retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArBoolean)); break; case typelib_TypeClass_BYTE:
retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArByte)); break; case typelib_TypeClass_SHORT:
retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArInt16)); break; case typelib_TypeClass_UNSIGNED_SHORT:
retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArUInt16)); break; case typelib_TypeClass_LONG:
retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArInt32)); break; case typelib_TypeClass_UNSIGNED_LONG:
retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArUInt32)); break; case typelib_TypeClass_HYPER:
retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArInt64)); break; case typelib_TypeClass_UNSIGNED_HYPER:
retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArUInt64)); break; case typelib_TypeClass_FLOAT:
retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArSingle)); break; case typelib_TypeClass_DOUBLE:
retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArDouble)); break; case typelib_TypeClass_STRING:
retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArString)); break; case typelib_TypeClass_TYPE:
retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArType)); break; case typelib_TypeClass_ANY: case typelib_TypeClass_ENUM: case typelib_TypeClass_EXCEPTION: case typelib_TypeClass_STRUCT: case typelib_TypeClass_INTERFACE: case typelib_TypeClass_SEQUENCE:
{
retVal= loadCliType(pTD->pTypeName); break;
} default: //All cases should be handled by the case statements above
OSL_ASSERT(0); break;
} break;
} default:
OSL_ASSERT(false); break;
} return retVal;
}
/** Otherwise a leading "unoidl." is removed.
*/
System::String^ mapUnoTypeName(rtl_uString const * typeName)
{
OUString usUnoName( const_cast< rtl_uString * >( typeName ) );
st::StringBuilder^ buf= gcnew st::StringBuilder(); //determine if the type is a sequence and its dimensions int dims= 0; if (usUnoName[0] == '[')
{
sal_Int32 index= 1; while (true)
{ if (usUnoName[index++] == ']')
dims++; if (usUnoName[index++] != '[') break;
}
usUnoName = usUnoName.copy(index - 1);
}
System::String ^ sUnoName = mapUnoString(usUnoName.pData); if (sUnoName->Equals(const_cast<System::String^>(Constants::usBool)))
buf->Append(const_cast<System::String^>(Constants::sBoolean)); elseif (sUnoName->Equals(const_cast<System::String^>(Constants::usChar)))
buf->Append(const_cast<System::String^>(Constants::sChar)); elseif (sUnoName->Equals(const_cast<System::String^>(Constants::usByte)))
buf->Append(const_cast<System::String^>(Constants::sByte)); elseif (sUnoName->Equals(const_cast<System::String^>(Constants::usShort)))
buf->Append(const_cast<System::String^>(Constants::sInt16)); elseif (sUnoName->Equals(const_cast<System::String^>(Constants::usUShort)))
buf->Append(const_cast<System::String^>(Constants::sUInt16)); elseif (sUnoName->Equals(const_cast<System::String^>(Constants::usLong)))
buf->Append(const_cast<System::String^>(Constants::sInt32)); elseif (sUnoName->Equals(const_cast<System::String^>(Constants::usULong)))
buf->Append(const_cast<System::String^>(Constants::sUInt32)); elseif (sUnoName->Equals(const_cast<System::String^>(Constants::usHyper)))
buf->Append(const_cast<System::String^>(Constants::sInt64)); elseif (sUnoName->Equals(const_cast<System::String^>(Constants::usUHyper)))
buf->Append(const_cast<System::String^>(Constants::sUInt64)); elseif (sUnoName->Equals(const_cast<System::String^>(Constants::usFloat)))
buf->Append(const_cast<System::String^>(Constants::sSingle)); elseif (sUnoName->Equals(const_cast<System::String^>(Constants::usDouble)))
buf->Append(const_cast<System::String^>(Constants::sDouble)); elseif (sUnoName->Equals(const_cast<System::String^>(Constants::usString)))
buf->Append(const_cast<System::String^>(Constants::sString)); elseif (sUnoName->Equals(const_cast<System::String^>(Constants::usVoid)))
buf->Append(const_cast<System::String^>(Constants::sVoid)); elseif (sUnoName->Equals(const_cast<System::String^>(Constants::usType)))
buf->Append(const_cast<System::String^>(Constants::sType)); elseif (sUnoName->Equals(const_cast<System::String^>(Constants::usXInterface)))
buf->Append(const_cast<System::String^>(Constants::sObject)); elseif (sUnoName->Equals(const_cast<System::String^>(Constants::usAny)))
{
buf->Append(const_cast<System::String^>(Constants::sAny));
} else
{ //put "unoidl." at the beginning
buf->Append(const_cast<System::String^>(Constants::sUnoidl)); //for polymorphic struct types remove the brackets, e.g mystruct<bool> -> mystruct
System::String ^ sName = mapUnoPolymorphicName(sUnoName);
buf->Append(sName);
} // append [] for (;dims--;)
buf->Append(const_cast<System::String^>(Constants::sBrackets));
return buf->ToString();
}
/** For example, there is a uno type com.sun.star.Foo<char, long>. The values in the type list are uno types and are replaced by cli types, such as System.Char, System.Int32, etc. The prefix unoidl is not added.
*/ inline System::String^ mapUnoPolymorphicName(System::String^ unoName)
{ return mapPolymorphicName(unoName, false);
}
/** For example, there is a type name such as com.sun.star.Foo<System.Char, System.Int32>. The values in the type list are CLI types and are replaced by uno types, such as char, long, etc. The prefix unoidl remains.
*/ inline System::String^ mapCliPolymorphicName(System::String^ unoName)
{ return mapPolymorphicName(unoName, true);
}
System::String^ mapPolymorphicName(System::String^ unoName, bool bCliToUno)
{ int index = unoName->IndexOf('<'); if (index == -1) return unoName;
System::Text::StringBuilder ^ builder = gcnew System::Text::StringBuilder(256);
builder->Append(unoName->Substring(0, index +1 ));
//Find the first occurrence of ',' //If the parameter is a polymorphic struct then we need to ignore everything //between the brackets because it can also contain commas //get the type list within < and > int endIndex = unoName->Length - 1;
index++; int cur = index; int countParams = 0; while (cur <= endIndex)
{
System::Char c = unoName[cur]; if (c == ',' || c == '>')
{ //insert a comma if needed if (countParams != 0)
builder->Append(",");
countParams++;
System::String ^ sParam = unoName->Substring(index, cur - index); //skip the comma
cur++; //the index to the beginning of the next param
index = cur; if (bCliToUno)
{
builder->Append(mapCliTypeName(sParam).getStr());
} else
{
OUString s = mapCliString(sParam);
builder->Append(mapUnoTypeName(s.pData));
}
} elseif (c == '<')
{
cur++; //continue until the matching '>' int numNested = 0; for (;;cur++)
{
System::Char curChar = unoName[cur]; if (curChar == '<')
{
numNested ++;
} elseif (curChar == '>')
{ if (numNested > 0)
numNested--; else break;
}
}
}
cur++;
}
OUString mapCliTypeName(System::String^ typeName)
{ int dims= 0; // Array? determine the "rank" (number of "[]") // move from the rightmost end to the left, for example // unoidl.PolymorphicStruct<System.Char[]>[] // has only a "dimension" of 1 int cur = typeName->Length - 1; bool bRightBracket = false; while (cur >= 0)
{
System::Char c = typeName[cur]; if (c == ']')
{
bRightBracket = true;
} elseif (c == '[')
{ if (!bRightBracket) throw BridgeRuntimeError( "Typename is wrong. No matching brackets for sequence. Name is: " +
mapCliString(typeName));
bRightBracket = false;
dims ++;
} else
{ if (bRightBracket) throw BridgeRuntimeError( "Typename is wrong. No matching brackets for sequence. Name is: " +
mapCliString(typeName)); break;
}
cur--;
}
if (bRightBracket || cur < 0) throw BridgeRuntimeError( "Typename is wrong. " +
mapCliString(typeName));
/** Maps uno types to dot net types. * If uno_data is null then the type description is converted to System::Type
*/ inline System::String^ mapUnoString( rtl_uString const * data)
{
assert(data); return gcnew System::String((__wchar_t*) data->buffer, 0, data->length);
}
// ToDo convert cli types to expected types, e.g a long to a short where the uno type // is a sal_Int16. This could be necessary if a scripting language (typeless) is used // @param assign the uno_data has to be destructed (in/out args) void Bridge::map_to_uno(void * uno_data, System::Object^ cli_data,
typelib_TypeDescriptionReference * type, bool assign) const
{ try{ switch (type->eTypeClass)
{ case typelib_TypeClass_VOID: break; case typelib_TypeClass_CHAR:
{
System::Char aChar= *safe_cast<System::Char^>(cli_data);
*(sal_Unicode*) uno_data= aChar; break;
} case typelib_TypeClass_BOOLEAN:
{
System::Boolean aBool= *safe_cast<System::Boolean^>(cli_data);
*(sal_Bool*)uno_data= aBool == true ? sal_True : sal_False; break;
} case typelib_TypeClass_BYTE:
{
System::Byte aByte= *safe_cast<System::Byte^>(cli_data);
*(sal_Int8*) uno_data= aByte; break;
} case typelib_TypeClass_SHORT:
{
System::Int16 aShort= *safe_cast<System::Int16^>(cli_data);
*(sal_Int16*) uno_data= aShort; break;
} case typelib_TypeClass_UNSIGNED_SHORT:
{
System::UInt16 aUShort= *safe_cast<System::UInt16^>(cli_data);
*(sal_uInt16*) uno_data= aUShort; break;
} case typelib_TypeClass_LONG:
{
System::Int32 aLong= *safe_cast<System::Int32^>(cli_data);
*(sal_Int32*) uno_data= aLong; break;
} case typelib_TypeClass_UNSIGNED_LONG:
{
System::UInt32 aULong= *safe_cast<System::UInt32^>(cli_data);
*(sal_uInt32*) uno_data= aULong; break;
} case typelib_TypeClass_HYPER:
{
System::Int64 aHyper= *safe_cast<System::Int64^>(cli_data);
*(sal_Int64*) uno_data= aHyper; break;
} case typelib_TypeClass_UNSIGNED_HYPER:
{
System::UInt64 aLong= *safe_cast<System::UInt64^>(cli_data);
*(sal_uInt64*) uno_data= aLong; break;
} case typelib_TypeClass_FLOAT:
{
System::Single aFloat= *safe_cast<System::Single^>(cli_data);
*(float*) uno_data= aFloat; break;
} case typelib_TypeClass_DOUBLE:
{
System::Double aDouble= *safe_cast<System::Double^>(cli_data);
*(double*) uno_data= aDouble; break;
} case typelib_TypeClass_STRING:
{ if (assign && *(rtl_uString**) uno_data)
rtl_uString_release(*(rtl_uString**) uno_data);
*(rtl_uString **)uno_data = 0; if (cli_data == nullptr)
{
rtl_uString_new((rtl_uString**) uno_data);
} else
{
System::String ^s= safe_cast<System::String^>(cli_data);
pin_ptr<constwchar_t> pdata= PtrToStringChars(s);
rtl_uString_newFromStr_WithLength( reinterpret_cast<rtl_uString **>(uno_data), reinterpret_cast<sal_Unicode const *>(pdata), s->Length);
} break;
} case typelib_TypeClass_TYPE:
{
typelib_TypeDescriptionReference* td= mapCliType(safe_cast<System::Type^>(
cli_data)); if (assign)
{
typelib_typedescriptionreference_release(
*(typelib_TypeDescriptionReference **)uno_data );
}
*(typelib_TypeDescriptionReference **)uno_data = td; break;
} case typelib_TypeClass_ANY:
{
uno_Any * pAny = (uno_Any *)uno_data; if (cli_data == nullptr) // null-ref or uninitialized any maps to empty any
{ if (assign)
uno_any_destruct( pAny, 0 );
uno_any_construct( pAny, 0, 0, 0 ); break;
}
uno::Any aAny= *safe_cast<uno::Any^>(cli_data);
css::uno::Type value_td( mapCliType(aAny.Type), SAL_NO_ACQUIRE);
if (assign)
uno_any_destruct( pAny, 0 );
try
{ switch (value_td.getTypeClass())
{ case css::uno::TypeClass_VOID:
pAny->pData = &pAny->pReserved; break; case css::uno::TypeClass_CHAR:
pAny->pData = &pAny->pReserved;
*(sal_Unicode*) &pAny->pReserved = *safe_cast<System::Char^>(aAny.Value); break; case css::uno::TypeClass_BOOLEAN:
pAny->pData = &pAny->pReserved;
*(sal_Bool *) &pAny->pReserved = *safe_cast<System::Boolean^>(aAny.Value); break; case css::uno::TypeClass_BYTE:
pAny->pData = &pAny->pReserved;
*(sal_Int8*) &pAny->pReserved = *safe_cast<System::Byte^>(aAny.Value); break; case css::uno::TypeClass_SHORT:
pAny->pData = &pAny->pReserved;
*(sal_Int16*) &pAny->pReserved = *safe_cast<System::Int16^>(aAny.Value); break; case css::uno::TypeClass_UNSIGNED_SHORT:
pAny->pData = &pAny->pReserved;
*(sal_uInt16*) &pAny->pReserved = *safe_cast<System::UInt16^>(aAny.Value); break; case css::uno::TypeClass_LONG:
pAny->pData = &pAny->pReserved;
*(sal_Int32*) &pAny->pReserved = *safe_cast<System::Int32^>(aAny.Value); break; case css::uno::TypeClass_UNSIGNED_LONG:
pAny->pData = &pAny->pReserved;
*(sal_uInt32*) &pAny->pReserved = *safe_cast<System::UInt32^>(aAny.Value); break; case css::uno::TypeClass_HYPER: if (sizeof (sal_Int64) <= sizeof (void *))
{
pAny->pData = &pAny->pReserved;
*(sal_Int64*) &pAny->pReserved = *safe_cast<System::Int64^>(aAny.Value);
} else
{
std::unique_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (sal_Int64) ) );
*(sal_Int64 *) mem.get()= *safe_cast<System::Int64^>(aAny.Value);
pAny->pData = mem.release();
} break; case css::uno::TypeClass_UNSIGNED_HYPER: if (sizeof (sal_uInt64) <= sizeof (void *))
{
pAny->pData = &pAny->pReserved;
*(sal_uInt64*) &pAny->pReserved = *safe_cast<System::UInt64^>(aAny.Value);
} else
{
std::unique_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (sal_uInt64) ) );
*(sal_uInt64 *) mem.get()= *safe_cast<System::UInt64^>(aAny.Value);
pAny->pData = mem.release();
} break; case css::uno::TypeClass_FLOAT: if (sizeof (float) <= sizeof (void *))
{
pAny->pData = &pAny->pReserved;
*(float*) &pAny->pReserved = *safe_cast<System::Single^>(aAny.Value);
} else
{
std::unique_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (float) ) );
*(float*) mem.get() = *safe_cast<System::Single^>(aAny.Value);
pAny->pData = mem.release();
} break; case css::uno::TypeClass_DOUBLE: if (sizeof (double) <= sizeof (void *))
{
pAny->pData = &pAny->pReserved;
*(double*) &pAny->pReserved= *safe_cast<System::Double^>(aAny.Value);
} else
{
std::unique_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (double) ) );
*(double*) mem.get()= *safe_cast<System::Double^>(aAny.Value);
pAny->pData= mem.release();
} break; case css::uno::TypeClass_STRING: // anies often contain strings; copy string directly
{
pAny->pData= &pAny->pReserved;
OUString _s = mapCliString(static_cast<System::String^>(aAny.Value));
pAny->pReserved= _s.pData;
rtl_uString_acquire(_s.pData); break;
} case css::uno::TypeClass_TYPE: case css::uno::TypeClass_ENUM: //ToDo copy enum direct case css::uno::TypeClass_SEQUENCE: case css::uno::TypeClass_INTERFACE:
pAny->pData = &pAny->pReserved;
pAny->pReserved = 0;
map_to_uno(
&pAny->pReserved, aAny.Value, value_td.getTypeLibType(), false/* no assign */); break; case css::uno::TypeClass_STRUCT: case css::uno::TypeClass_EXCEPTION:
{
css::uno::Type anyType(value_td);
typelib_TypeDescription* td= NULL;
anyType.getDescription(&td);
std::unique_ptr< rtl_mem > mem(rtl_mem::allocate(td->nSize));
typelib_typedescription_release(td);
map_to_uno(
mem.get(), aAny.Value, value_td.getTypeLibType(), false/* no assign */);
pAny->pData = mem.release(); break;
} default:
{ throw BridgeRuntimeError("[map_to_uno():" + value_td.getTypeName() + "] unsupported value type of any!");
}
}
} catch(System::InvalidCastException^ )
{ // ToDo check this if (assign)
uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any
OUString str = "[map_to_uno():Any" + value_td.getTypeName() + "]The Any type " + value_td.getTypeName() + " does not correspond to its value type: "; if(aAny.Value != nullptr)
{
css::uno::Type td(mapCliType(aAny.Value->GetType()), SAL_NO_ACQUIRE);
str += td.getTypeName();
} if (assign)
uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any throw BridgeRuntimeError(str);
} catch (BridgeRuntimeError& )
{ if (assign)
uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any throw;
} catch (...)
{ if (assign)
uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any throw;
}
pAny->pType = value_td.getTypeLibType();
typelib_typedescriptionreference_acquire(pAny->pType); break;
} case typelib_TypeClass_ENUM:
{ // InvalidCastException is caught at the end of this method
System::Int32 aEnum= System::Convert::ToInt32((cli_data));
*(sal_Int32*) uno_data = aEnum; break;
} case typelib_TypeClass_STRUCT: case typelib_TypeClass_EXCEPTION:
{
css::uno::TypeDescription td(type);
typelib_CompoundTypeDescription * comp_td =
(typelib_CompoundTypeDescription*) td.get();
/** @param info The expected target type. Currently info is provided when this method is called to convert the in/out and out parameters of a call from cli to uno. Then info is always a byref type, e.g. "System.String&". info is used for Any and Enum conversion. @param bDontCreateObj false - a new object is created which holds the mapped uno value and is assigned to cli_data. true - cli_data already contains the newly constructed object. This is the case if a struct is converted then on the first call to map_to_cli the new object is created. If the struct inherits another struct then this function is called recursively while the newly created object is passed in cli_data.
*/ void Bridge::map_to_cli(
System::Object^ *cli_data, voidconst * uno_data,
typelib_TypeDescriptionReference * type, System::Type^ info, bool bDontCreateObj) const
{ switch (type->eTypeClass)
{ case typelib_TypeClass_CHAR:
*cli_data= *(__wchar_tconst*)uno_data; break; case typelib_TypeClass_BOOLEAN:
*cli_data = (*(boolconst*)uno_data) == sal_True; break; case typelib_TypeClass_BYTE:
*cli_data = *(unsignedcharconst*) uno_data; break; case typelib_TypeClass_SHORT:
*cli_data= *(shortconst*) uno_data; break; case typelib_TypeClass_UNSIGNED_SHORT:
*cli_data= *(unsignedshortconst*) uno_data; break; case typelib_TypeClass_LONG:
*cli_data= *(intconst*) uno_data; break; case typelib_TypeClass_UNSIGNED_LONG:
*cli_data= *(unsignedintconst*) uno_data; break; case typelib_TypeClass_HYPER:
*cli_data= *(__int64 const*) uno_data; break; case typelib_TypeClass_UNSIGNED_HYPER:
*cli_data= *(unsigned __int64 const*) uno_data; break; case typelib_TypeClass_FLOAT:
*cli_data= *(floatconst*) uno_data; break; case typelib_TypeClass_DOUBLE:
*cli_data= *(doubleconst*) uno_data; break; case typelib_TypeClass_STRING:
{
rtl_uString const* sVal= NULL;
sVal= *(rtl_uString* const*) uno_data;
*cli_data= gcnew System::String((__wchar_t*) sVal->buffer,0, sVal->length); break;
} case typelib_TypeClass_TYPE:
{
*cli_data= mapUnoType( *(typelib_TypeDescriptionReference * const *)uno_data ); break;
} case typelib_TypeClass_ANY:
{
uno_Any const * pAny = (uno_Any const *)uno_data; if (typelib_TypeClass_VOID != pAny->pType->eTypeClass)
{
System::Object^ objCli= nullptr;
map_to_cli(
&objCli, pAny->pData, pAny->pType, nullptr, false);
uno::Any anyVal(mapUnoType(pAny->pType), objCli);
*cli_data= anyVal;
} else
{ // void any
*cli_data= uno::Any::VOID;
} break;
} case typelib_TypeClass_ENUM:
{ if (info != nullptr)
{
OSL_ASSERT(info->IsByRef);
info= info->GetElementType();
*cli_data= System::Enum::ToObject(info, *(System::Int32*) uno_data);
} else
*cli_data= System::Enum::ToObject(
mapUnoType(type), *(System::Int32*) uno_data); break;
} case typelib_TypeClass_STRUCT: case typelib_TypeClass_EXCEPTION:
{
TypeDescr td( type );
typelib_CompoundTypeDescription * comp_td =
(typelib_CompoundTypeDescription *) td.get(); if ( ! ((typelib_TypeDescription*) comp_td)->bComplete)
::typelib_typedescription_complete(
(typelib_TypeDescription**) & comp_td );
//create the type
System::Type^ cliType= loadCliType(td.get()->pTypeName); //detect if we recursively convert inherited structures //If this point is reached because of a recursive call during covering a //struct then we must not create a new object rather we use the one in // cli_data argument.
System::Object^ cliObj; if (bDontCreateObj)
cliObj = *cli_data; // recursive call else
{ //Special handling for Exception conversion. We must call constructor System::Exception //to pass the message string if (ucss::uno::Exception::typeid->IsAssignableFrom(cliType))
{ //We need to get the Message field. Therefore we must obtain the offset from //the typedescription. The base interface of all exceptions is //com::sun::star::uno::Exception which contains the message
typelib_CompoundTypeDescription* pCTD = comp_td; while (pCTD->pBaseTypeDescription)
pCTD = pCTD->pBaseTypeDescription; int nPos = -1;
OUString usMessageMember("Message"); for (int i = 0; i < pCTD->nMembers; i ++)
{ if (usMessageMember.equals(pCTD->ppMemberNames[i]))
{
nPos = i; break;
}
}
OSL_ASSERT (nPos != -1); int offset = pCTD->pMemberOffsets[nPos]; //With the offset within the exception we can get the message string
System::String^ sMessage = mapUnoString(*(rtl_uString**)
((char*) uno_data + offset)); //We need to find a constructor for the exception that takes the message string //We assume that the first argument is the message string
cli::array<sr::ConstructorInfo^>^ arCtorInfo = cliType->GetConstructors();
sr::ConstructorInfo^ ctorInfo = nullptr; int numCtors = arCtorInfo->Length; //Constructor must at least have 2 params for the base //unoidl.com.sun.star.uno.Exception (String, Object);
cli::array<sr::ParameterInfo^>^ arParamInfo; for (int i = 0; i < numCtors; i++)
{
--> --------------------
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.