问题
I want to write a block, which sends all image files from selected directory.
Images are of different sizes, so output signal size should vary.
Unfortunately I was unable to find a way to change signal size at each step. There are many of undocumented features here, in examples like
block.OutputPort(1).DimensionsMode = 'Variable';
and
block.OutputPort(1).CurrentDimensions = [1 block.InputPort(1).Data];
and so on. I was unable to deduce correct way to operate all this stuff yet...
UPDATE
For example, this S-function
function Test_SF_01(block)
% Level-2 MATLAB file S-Function.
setup(block);
function setup(block)
% Register number of ports and parameters
block.NumInputPorts = 0;
block.NumOutputPorts = 1;
block.NumDialogPrms = 0;
% Setup functional port properties to dynamically inherited
block.SetPreCompOutPortInfoToDynamic;
% Register the properties of the output port
block.OutputPort(1).DimensionsMode = 'Variable';
block.OutputPort(1).SamplingMode = 'Sample';
% Register sample times
% [-1, 0] : Inherited sample time
block.SampleTimes = [-1 0];
% Register methods called at run-time
block.RegBlockMethod('Outputs', @Outputs);
function Outputs(block)
block.OutputPort(1).CurrentDimensions = floor(rand(1,2)*10)+1;
causes an error
Invalid variable dimensions assignment for output port 1 of 'Test_01/Level-2 MATLAB S-Function'. The number of variable dimensions is 1. However, the length of the MATLAB array is 2
why?
回答1:
The following S-function generates variable dimension signal. They key problem was that initial set of Dimensions
property defines MAXIMAL values of dimensions, which is absolutely not clear from docs, while error messages are mostly irrelevant.
function Test_SF_01(block)
% Level-2 MATLAB file S-Function.
setup(block);
function setup(block)
% Register number of ports and parameters
block.NumInputPorts = 0;
block.NumOutputPorts = 1;
block.NumDialogPrms = 0;
% Setup functional port properties to dynamically inherited
block.SetPreCompOutPortInfoToDynamic;
% Register the properties of the output port
block.OutputPort(1).DimensionsMode = 'Variable';
block.OutputPort(1).Dimensions = [10000 10000];
block.OutputPort(1).SamplingMode = 'Sample';
% Register sample times
% [-1, 0] : Inherited sample time
block.SampleTimes = [-1 0];
% Register methods called at run-time
block.RegBlockMethod('Outputs', @Outputs);
function Outputs(block)
dims = floor(rand(1,2)*10)+1;
block.OutputPort(1).CurrentDimensions = dims;
data = rand(dims);
block.OutputPort(1).Data = data;
回答2:
Have you also looked at the following code example from the doc? See Operations for Variable-Size Signals. There's a bit more in there than what you have in your code. Probably best to start from the basic template msfuntmpl_basic.m
as they do in the doc.
function setup(block)
% Register the properties of the output port
block.OutputPort(1).DimensionsMode = 'Variable';
block.RegBlockMethod('SetInputPortDimensionsMode', @SetInputDimsMode);
function DoPostPropSetup(block)
%Register dependency rules to update current output size of output port a depending on
%input ports b and c
block.AddOutputDimsDependencyRules(a, [b c], @setOutputVarDims);
%Configure output port b to have the same dimensions as input port a
block.InputPortSameDimsAsOutputPort(a,b);
%Configure DWork a to have its size reset when input size changes.
block.DWorkRequireResetForSignalSize(a,true);
function SetInputDimsMode(block, port, dm)
% Set dimension mode
block.InputPort(port).DimensionsMode = dm;
block.OutputPort(port).DimensionsMode = dm;
function setOutputVarDims(block, opIdx, inputIdx)
% Set current (run-time) dimensions of the output
outDimsAfterReset = block.InputPort(inputIdx(1)).CurrentDimensions;
block.OutputPort(opIdx).CurrentDimensions = outDimsAfterReset;
来源:https://stackoverflow.com/questions/17703376/how-to-write-s-function-with-variable-size-of-output-signal