/* -*- 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 .
*/
staticinlinevoid emit_ldarg( Emit::ILGenerator ^ code, ::System::Int32 index )
{ switch (index)
{ case 0: #pragma warning (push) #pragma warning (disable: 4538) // const/volatile qualifiers on this type are not supported
code->Emit( Emit::OpCodes::Ldarg_0 ); #pragma warning (pop) break; case 1:
code->Emit( Emit::OpCodes::Ldarg_1 ); break; case 2:
code->Emit( Emit::OpCodes::Ldarg_2 ); break; case 3:
code->Emit( Emit::OpCodes::Ldarg_3 ); break; default: if (index < 0x100)
code->Emit( Emit::OpCodes::Ldarg_S, (::System::Byte) index ); elseif (index < 0x8000)
code->Emit( Emit::OpCodes::Ldarg_S, (::System::Int16) index ); else
code->Emit( Emit::OpCodes::Ldarg, index ); break;
}
}
void polymorphicStructNameToStructName(::System::String ^* sPolyName)
{ if ((*sPolyName)->EndsWith(">") == false) return;
int index = (*sPolyName)->IndexOf('<');
OSL_ASSERT(index != -1);
*sPolyName = (*sPolyName)->Substring(0, index);
}
System::String^ mapUnoTypeName(System::String ^ typeName)
{
::System::Text::StringBuilder^ buf= gcnew System::Text::StringBuilder();
::System::String ^ sUnoName = ::System::String::Copy(typeName); //determine if the type is a sequence and its dimensions int dims= 0; if (typeName->StartsWith("["))//if (usUnoName[0] == '[')
{ int index= 1; while (true)
{ if (typeName[index++] == ']')//if (usUnoName[index++] == ']')
dims++; if (typeName[index++] != '[')//usUnoName[index++] != '[') break;
}
sUnoName = sUnoName->Substring(index - 1);//usUnoName = usUnoName.copy(index - 1);
} if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoBool)))
buf->Append(const_cast<System::String^>(Constants::sBoolean)); elseif (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoChar)))
buf->Append(const_cast<System::String^>(Constants::sChar)); elseif (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoByte)))
buf->Append(const_cast<System::String^>(Constants::sByte)); elseif (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoShort)))
buf->Append(const_cast<System::String^>(Constants::sInt16)); elseif (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoUShort)))
buf->Append(const_cast<System::String^>(Constants::sUInt16)); elseif (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoLong)))
buf->Append(const_cast<System::String^>(Constants::sInt32)); elseif (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoULong)))
buf->Append(const_cast<System::String^>(Constants::sUInt32)); elseif (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoHyper)))
buf->Append(const_cast<System::String^>(Constants::sInt64)); elseif (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoUHyper)))
buf->Append(const_cast<System::String^>(Constants::sUInt64)); elseif (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoFloat)))
buf->Append(const_cast<System::String^>(Constants::sSingle)); elseif (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoDouble)))
buf->Append(const_cast<System::String^>(Constants::sDouble)); elseif (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoString)))
buf->Append(const_cast<System::String^>(Constants::sString)); elseif (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoVoid)))
buf->Append(const_cast<System::String^>(Constants::sVoid)); elseif (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoType)))
buf->Append(const_cast<System::String^>(Constants::sType)); elseif (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoXInterface)))
buf->Append(const_cast<System::String^>(Constants::sObject)); elseif (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoAny)))
{
buf->Append(const_cast<System::String^>(Constants::sAny));
} else
{ //put "unoidl." at the beginning
buf->Append(const_cast<System::String^>(Constants::sUnoidl));
buf->Append(mapUnoPolymorphicName(sUnoName));
} // 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.
Strings can be as complicated as this test.MyStruct<char,test.MyStruct<long, []string>>
*/
System::String^ mapUnoPolymorphicName(System::String^ unoName)
{ int index = unoName->IndexOf('<'); if (index == -1) return unoName;
System::Text::StringBuilder ^ builder =
gcnew System::Text::StringBuilder(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;
builder->Append(mapUnoTypeName(sParam));
} 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++;
}
if (nullptr == ret_type)
{
sal_Int32 len = m_extra_assemblies->Length; for ( sal_Int32 pos = 0; pos < len; ++pos )
{
ret_type = m_extra_assemblies[ pos ]->GetType(
cts_name, false/* no exc */ ); if (nullptr != ret_type)
{ if (g_bVerbose)
{
::System::Console::WriteLine( "> resolving type {0} from {1}.",
cts_name, ret_type->Assembly->FullName );
} break;
}
}
} if (nullptr != ret_type) return ret_type->Assembly; return nullptr;
}
::System::Type ^ TypeEmitter::get_type(
::System::String ^ cts_name, bool throw_exc )
{
::System::Type ^ ret_type = m_module_builder->GetType( cts_name, false ); //We get the type from the ModuleBuilder even if the type is not complete //but have been defined. //if (ret_type == 0) //{ // iface_entry * entry = dynamic_cast< iface_entry * >( // m_incomplete_ifaces->get_Item( cts_name ) ); // if (0 != entry) // ret_type = entry->m_type_builder; //} //try the cli_basetypes assembly if (ret_type == nullptr)
{
::System::Text::StringBuilder ^ builder = gcnew ::System::Text::StringBuilder(cts_name);
builder->Append(",cli_basetypes");
ret_type = ::System::Type::GetType(builder->ToString());
}
if (ret_type == nullptr)
{ try
{ // may call on type_resolve() return ::System::Type::GetType( cts_name, throw_exc );
} catch (::System::Exception^ exc)
{ //If the type is not found one may have forgotten to specify assemblies with //additional types
::System::Text::StringBuilder ^ sb = gcnew ::System::Text::StringBuilder();
sb->Append(gcnew ::System::String("\nThe type "));
sb->Append(cts_name);
sb->Append(gcnew ::System::String(" \n could not be found. Did you forget to " "specify an additional assembly with the --reference option?\n")); if (throw_exc) throw gcnew ::System::Exception(sb->ToString(), exc);
}
} else
{ return ret_type;
}
}
//In case of an instantiated polymorphic struct we want to return a //uno.PolymorphicType (inherits Type) rather than Type. This is needed for constructing //the service code. We can only do that if the struct is completed. if (m_generated_structs[cts_name])
{
Reference< reflection::XStructTypeDescription> xStructTypeDesc(
xType, UNO_QUERY);
Sequence<Reference< reflection::XTypeDescription > > seqBaseTypes( xType->getBaseTypes() ); if (seqBaseTypes.getLength() > 0)
{ for (int i = 0; i < seqBaseTypes.getLength(); i++)
{ //make sure we get the interface rather than a typedef
Reference<reflection::XInterfaceTypeDescription2> aBaseType =
resolveInterfaceTypedef( seqBaseTypes[i]);
if ( aBaseType->getName() != "com.sun.star.uno.XInterface" )
{
::System::String ^ basetype_name = to_cts_name( aBaseType->getName() );
iface_entry ^ base_entry = dynamic_cast< iface_entry ^ >(
m_incomplete_ifaces[basetype_name] ); if (nullptr != base_entry)
{ // complete uncompleted base type first
complete_iface_type( base_entry );
}
}
}
}
const Sequence<
Reference< reflection::XMethodParameter > > seq_parameters(
xMethod->getParameters() );
sal_Int32 params_length = seq_parameters.getLength();
array< ::System::Type^>^ param_types =
gcnew array< ::System::Type^>( params_length ); // first determine all types //Make the first param type as return type
sal_Int32 params_pos = 0; for ( ; params_pos < params_length; ++params_pos )
{
Reference< reflection::XMethodParameter > const & xParam =
seq_parameters[ params_pos ];
::System::Type ^ param_type = get_type( xParam->getType() );
::System::String ^ param_type_name = param_type->FullName; if (xParam->isOut())
{
param_type = get_type(
::System::String::Concat(
param_type_name, "&" ), true );
}
param_types[ xParam->getPosition() ] = param_type;
}
// create method // if (tb) // method_builder = type_builder->DefineMethod( // ustring_to_String( xMethod->getMemberName() ), // c_method_attr, tb, // param_types ); // else
Emit::MethodBuilder ^ method_builder = type_builder->DefineMethod(
ustring_to_String( xMethod->getMemberName() ),
c_method_attr, get_type( xMethod->getReturnType() ),
param_types ); // then define parameter infos
params_pos = 0; for ( ; params_pos < params_length; ++params_pos )
{
Reference< reflection::XMethodParameter > const & xParam =
seq_parameters[ params_pos ]; long param_flags = 0; if (xParam->isIn())
param_flags |= (long)ParameterAttributes::In; if (xParam->isOut())
param_flags |= (long)ParameterAttributes::Out;
OSL_ASSERT( 0 != param_flags );
method_builder->DefineParameter(
xParam->getPosition() +1 /* starts with 1 */,
(ParameterAttributes) param_flags,
ustring_to_String( xParam->getName() ) );
} //Apply attribute TypeParametersAttribute to return value if it //is a parameterized Type. Currently only structs can have parameters.
Reference<reflection::XStructTypeDescription> xReturnStruct(
xMethod->getReturnType(), UNO_QUERY);
if (xReturnStruct.is())
{ const Sequence<Reference<reflection::XTypeDescription> > seq_type_args =
xReturnStruct->getTypeArguments(); if (seq_type_args.getLength() != 0)
{ //get the ctor of the attribute
array< ::System::Type^>^ arCtor = {::System::Type::GetType("System.Type[]")}; //Get the arguments for the attribute's ctor int numTypes = seq_type_args.getLength();
array< ::System::Type^>^ arCtsTypes = gcnew array< ::System::Type^>(numTypes); for (int i = 0; i < numTypes; i++)
arCtsTypes[i] = get_type(seq_type_args[i]);
array< ::System::Object^>^ arArgs = {arCtsTypes};
//Polymorphic struct, define uno.TypeParametersAttribute //A polymorphic struct cannot have a basetype. //When we create the template of the struct then we have no exact types //and the name does not contain a parameter list
Sequence< OUString > seq_type_parameters;
Reference< reflection::XStructTypeDescription> xStructTypeDesc(
entry->m_xType, UNO_QUERY); if (xStructTypeDesc.is())
{
seq_type_parameters = xStructTypeDesc->getTypeParameters(); int numTypes = 0; if ((numTypes = seq_type_parameters.getLength()) > 0)
{
array< ::System::Object^>^ aArg = gcnew array< ::System::Object^>(numTypes); for (int i = 0; i < numTypes; i++)
aArg[i] = ustring_to_String(seq_type_parameters[i]);
array< ::System::Object^>^ args = {aArg};
// optional: lookup base type whether generated entry of this session
struct_entry ^ base_type_entry = nullptr; if (nullptr != entry->m_base_type)
{ //ToDo maybe get from incomplete structs
base_type_entry = dynamic_cast< struct_entry ^ >(
m_generated_structs[
entry->m_base_type->FullName ] );
}
// members const Sequence< Reference< reflection::XTypeDescription > > seq_members(
entry->m_xType->getMemberTypes() ); const Sequence< OUString > seq_member_names( entry->m_xType->getMemberNames() );
sal_Int32 members_length = seq_members.getLength();
OSL_ASSERT( seq_member_names.getLength() == members_length ); //check if we have a XTypeDescription for every member. If not then the user may //have forgotten to specify additional rdbs with the --extra option. for (int i = 0; i < members_length; i++)
{ const OUString sType(entry->m_xType->getName()); const OUString sMemberName(seq_member_names[i]); if ( ! seq_members[i].is()) throw RuntimeException("Missing type description . Check if you need to " "specify additional RDBs with the --extra option. Type missing for: " + sType + "::" + sMemberName,0);
}
int curParamIndex = 0; //count the fields which have parameterized types for ( member_pos = 0; member_pos < members_length; ++member_pos )
{
::System::String ^ field_name =
ustring_to_String( seq_member_names[ member_pos ] );
::System::Type ^ field_type; //Special handling of struct parameter types bool bParameterizedType = false; if (seq_members[ member_pos ]->getTypeClass() == TypeClass_UNKNOWN)
{
bParameterizedType = true; if (type_param_pos < seq_type_parameters.getLength())
{
field_type = ::System::Object::typeid;
type_param_pos++;
} else
{ throw RuntimeException( "unexpected member type in " + entry->m_xType->getName() );
}
} else
{
field_type = get_type( seq_members[ member_pos ] );
if (field_type->IsArray
&& m_incomplete_structs[cts_name]
&& !field_type->Namespace->Equals("System"))
{ //Find the value type. In case of sequence<sequence< ... > > find the actual value type
::System::Type ^ value = field_type; while ((value = value->GetElementType())->IsArray); //If the value type is a struct then make sure it is fully created.
get_complete_struct(value->FullName);
field_type = get_type(seq_members[member_pos]);
}
}
members[ member_pos ] =
entry->m_type_builder->DefineField(
field_name, field_type, FieldAttributes::Public );
//parameterized type (polymorphic struct) ? if (bParameterizedType && xStructTypeDesc.is())
{ //get the name
OSL_ASSERT(seq_type_parameters.getLength() > curParamIndex);
::System::String^ sTypeName = ustring_to_String(
seq_type_parameters[curParamIndex++]);
array< ::System::Object^>^ args = {sTypeName}; //set ParameterizedTypeAttribute
array< ::System::Type^>^ arCtorTypes = {::System::String::typeid};
if (g_bVerbose)
{
::System::Console::WriteLine( "> emitting {0} type {1}",
TypeClass_STRUCT == entry->m_xType->getTypeClass()
? "struct"
: "exception",
cts_name);
} // new entry
m_generated_structs->Add(cts_name, entry );
::System::Type ^ ret_type = entry->m_type_builder->CreateType();
// remove from incomplete types map
m_incomplete_structs->Remove( cts_name );
entry->m_xType->release();
if (g_bVerbose)
{
::System::Console::WriteLine( "> emitting struct type {0}", cts_name);
} return ret_type;
}
//Examples of generated code // public static XWeak constructor1(XComponentContext ctx) // { // XMultiComponentFactory factory = ctx.getServiceManager(); // if (factory == null) // throw new com.sun.star.uno.DeploymentException("bla", null); // return (XWeak) factory.createInstanceWithContext("service_specifier", ctx); // } // public static XWeak constructor2(XComponentContext ctx, int a, int b, Any c) // { // XMultiComponentFactory factory = ctx.getServiceManager(); // if (factory == null) // throw new com.sun.star.uno.DeploymentException("bla", null); // Any[] arAny = new Any[3]; // arAny[0] = new Any(typeof(int), a); // arAny[1] = new Any(typeof(int), b); // arAny[2] = new Any(c.Type, c.Value); // return (XWeak) factory.createInstanceWithArgumentsAndContext("service_specifier", arAny, ctx); // } // Notice that an any parameter is NOT wrapped by another any. Instead the new any is created with the type and value // of the parameter.
//Create the service constructors. //obtain the interface which makes up this service, it is the return //type of the constructor functions
Reference<reflection::XInterfaceTypeDescription2> xIfaceType(
xServiceType->getInterface(), UNO_QUERY); if (xIfaceType.is () == sal_False)
xIfaceType = resolveInterfaceTypedef(xServiceType->getInterface());
System::Type ^ retType = get_type(xIfaceType);
//Create the ConstructorInfo for a DeploymentException
::System::Type ^ typeDeploymentExc =
get_type("unoidl.com.sun.star.uno.DeploymentException", true);
for (int j = seqCtors.getLength() - 1; j >= 0; j--)
{ bool bParameterArray = false;
::System::Type ^ typeAny = ::uno::Any::typeid; const Reference<reflection::XServiceConstructorDescription> & ctorDes =
seqCtors[j]; //obtain the parameter types const Sequence<Reference<reflection::XParameter> > seqParams =
ctorDes->getParameters();
sal_Int32 cParams = seqParams.getLength();
array< ::System::Type^>^ arTypeParameters = gcnew array< ::System::Type^> (cParams + 1);
arTypeParameters[0] = get_type("unoidl.com.sun.star.uno.XComponentContext", true); for (int iparam = 0; iparam != cParams; iparam++)
{ if (seqParams[iparam]->isRestParameter())
arTypeParameters[iparam + 1] = array< ::uno::Any>::typeid; else
arTypeParameters[iparam + 1] = get_type(seqParams[iparam]->getType());
} //The array arTypeParameters can contain: //System.Type and uno.PolymorphicType. //Passing PolymorphicType to MethodBuilder.DefineMethod will cause a problem. //The exception will read something like no on information for parameter # d //Maybe we need no override another Type method in PolymorphicType ... //Until we have figured this out, we will create another array of System.Type which //we pass on to DefineMethod.
array< ::System::Type^>^ arParamTypes = gcnew array< ::System::Type^> (cParams + 1); // arParamTypes[0] = get_type("unoidl.com.sun.star.uno.XComponentContext", true); for (int i = 0; i < cParams + 1; i++)
{
::uno::PolymorphicType ^ pT = dynamic_cast< ::uno::PolymorphicType ^ >(arTypeParameters[i]); if (pT)
arParamTypes[i] = pT->OriginalType; else
arParamTypes[i] = arTypeParameters[i];
} //define method
System::String ^ ctorName; if (ctorDes->isDefaultConstructor())
ctorName = gcnew ::System::String("create"); else
ctorName = ustring_to_String(ctorDes->getName());
Emit::MethodBuilder^ method_builder = type_builder->DefineMethod(
ctorName, static_cast<MethodAttributes>(MethodAttributes::Public | MethodAttributes::HideBySig |
MethodAttributes::Static),
retType, // arTypeParameters);
arParamTypes);
//define UNO exception attribute (exceptions)--------------------------------------
Emit::CustomAttributeBuilder^ attrBuilder = get_service_exception_attribute(ctorDes); if (attrBuilder != nullptr)
method_builder->SetCustomAttribute(attrBuilder);
//define parameter attributes (paramarray), names etc. //The first parameter is the XComponentContext, which cannot be obtained //from reflection. //The context is not part of the idl description
method_builder->DefineParameter(
1, ParameterAttributes::In, "the_context");
//The return type
Emit::LocalBuilder^ local_return_val =
ilGen->DeclareLocal(retType);
//Obtain the XMultiComponentFactory and throw an exception if we do not get one
ilGen->Emit(Emit::OpCodes::Ldarg_0);
::System::Reflection::MethodInfo ^ methodGetServiceManager = get_type( "unoidl.com.sun.star.uno.XComponentContext", true)
->GetMethod("getServiceManager");
ilGen->Emit(Emit::OpCodes::Callvirt, methodGetServiceManager);
ilGen->Emit(Emit::OpCodes::Stloc, local_factory);
ilGen->Emit(Emit::OpCodes::Ldloc, local_factory);
Emit::Label label1 = ilGen->DefineLabel();
ilGen->Emit(Emit::OpCodes::Brtrue, label1); //The string for the exception
::System::Text::StringBuilder ^ strbuilder = gcnew ::System::Text::StringBuilder(256);
strbuilder->Append("The service ");
strbuilder->Append(to_cts_name(xServiceType->getName()));
strbuilder->Append(" could not be created. The context failed to supply the service manager.");
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5
¤ Dauer der Verarbeitung: 0.64 Sekunden
(vorverarbeitet)
¤
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 und die Messung sind noch experimentell.