AnyNumber type for inputs and outputs

Hi,

I’m designing a C++ based component where certain inputs can be any number, and I’d like to simply “pass them through” to the output provided they meet some conditions. The “pass-through” behavior is similar to what the Bypass or Resampler component does, but modified for our purpose.
I tried using MAPS::AnyNumber to define the output stream,

MAPS_OUTPUT(OUTPUT_SIG1, MAPS::AnyNumber, NULL, NULL, 1)

and then wrote to the output stream,

MAPS::OutputGuard<MAPSFloat64> output_1(this, Output(OUTPUT_SIG1));
 output_1.Data() = 10;
 output_1.VectorSize() = 1;

but this results in a run-time error

Error: signal_forwarder_1: maps_io_access.hpp:675 __cdecl MAPS::OutputGuard::OutputGuard(class maps_SignalForwarder *,class MAPSOutput &,const bool): The ElementType of the OutputGuard of [output_name:signal1_out] doesn’t match the actual type of the output

I tried looking for examples in the SDK but couldn’t find anything demonstrating this. How should I be making this component? Alternatively, how is the Bypass component achieving this behavior?

Hi Darsh,

While you can have a generic type like that, the output buffer size always has to be well defined during run time, and for that you need to define the output type. You can see this behavior by observing the Bypass component as well. Initially the output port has any type, but after receiving the first input, the output will be limited in type to just that one.

The way you do this is by putting the following into your Core method:

    if (firstTimeWriting)
    {
        Output(OUTPUT_SIG1).SetTypeValue(inData.Type().value);
        Output(OUTPUT_SIG1).AllocOutputBuffer(1);
        firstTimeWriting = false;
    }

Here firstTimeWriting is a boolean member variable of the component class. Also make sure in your original output definition, you have the buffer size as 0 and not 1, since you allocate the buffer size after defining the type.

Then in Death you can put

Output(OUTPUT_SIG1).SetTypeValue(MAPS::AnyNumber)

to change the type back to any again.

Thanks a lot Lukas!
Along the same lines, how can I work with inputs of any type, for example

MAPS_INPUT(INPUT_SIG, MAPS::FilterNumber, MAPS::SamplingReader)

My intent behind this is to take in any integer/float value, and only output it if certain conditions are met. The output type is fixed. I realize a simple solution could be to access the Data value from the IOElt object, but I was trying to do this using an InputGaurd. It’s expected syntax is:

MAPS::InputGuard<datatype>  input(this, Input(INPUT_SIG));

and requires hardcoding a datatype. But then if the incoming input is of a different type, the block generates an error similar to the one for the OutputGuard in the original post (about type mismatch).
Is there a way to make use of Input Guards for this case or should I simply use the underlying IOElt system?

Hi Darsh,

Both the IOElt and Input/Output Guard are viable options. With Input/Output Guard, you can create one using <void> type. With the void guard, you just can’t use the Data() function because it doesn’t know what type it is, but you can still work with the pointers using DataPointer() or DataPointerAs().

So if you wanted to copy from the inputGuard to the outputGuard data, you could do:

bool tmp = true;
memcpy(outputGuard.DataPointer(), inputGuard.DataPointer(), inputGuard.IOEltBufferSizeInBytes(&tmp));

You could do something similar if you use IOElt.