How to use optional parameters with QAxFactory based API

1

I'm currently implementing an QAxFactory based COM-Api and want to give some of the functions default parameters. However, this seems not to work since when I call said functions without these default parameters I receive an error (HRESULT: 0x80020005 (DISP_E_TYPEMISMATCH)).

I found some advice about linking signals and slots within a program (like linking QML and C++ code https://doc.qt.io/qt-5/signalsandslots-syntaxes.html) but that's not what I'm looking for and I don't how or if I can use that for my case. A minimal example:

public slots:

void function (QString foo, bool bar = false); //so providing bar when calling function should be optional

When calling this (in my case from Visual Studio, where I write unit tests in c#), I find this:

Api.function ("bla", true); //this works
Api.function ("bla"); //this gives the above error

Any help would be greatly appreciated. Also I'd appreciate feedback to the question style since this is my first question ever here.

c++
qt
asked on Stack Overflow Aug 26, 2019 by Skuamato • edited Aug 26, 2019 by MindSwipe

1 Answer

1

This is because optional parameters don't exist. Methods with optional parameters get compiled to standard methods without optional parameters.

But then, how do they work? Well, you see the compiler doesn't only change the method with the optional parameters, but also changes the code invoking the optional parameters. Take this code as an example:

using System;

namespace OptionalParameterDemo
{
    public class Program
    {
        public static void Main(string[] args)
        {
            OptionalParameters();
            OptionalParameters("Bar");
        }

        private static void OptionalParameters(string foo = "Hello World")
        {
            Console.WriteLine(foo);
        }
    }
}

Using a decompiler like SharpLab we can see the decompiled source. And lo and behold we see that the OptionalParameters call was altered:

using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
namespace OptionalParametersDemo
{
    public class Program
    {
        public static void Main(string[] args)
        {
            // Notice how this changed to include "Hello World"
            OptionalParameters("Hello World");
            OptionalParameters("Bar");
        }

        private static void OptionalParameters(string foo)
        {
            Console.WriteLine(foo);
        }
    }
}

So if we would now use something like P/Invoke to call the method OptionalParameters and not supply it with a parameter (as we think it's optional) it would throw an exception, so instead of using optional parameters we need to use an overload, so the parameter has a constant

answered on Stack Overflow Aug 26, 2019 by MindSwipe

User contributions licensed under CC BY-SA 3.0