Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Calling C

A POU marked {external} has its implementation somewhere else. The compiler takes the declaration, generates no body, and leaves the symbol for the linker.

{external}
FUNCTION log: DINT
    VAR_IN_OUT
        message: STRING[1024];
    END_VAR
    VAR_INPUT
        severity: (Err, Warn, Info) := Info;
    END_VAR
END_FUNCTION

log can now be called from Structured Text. At link time a function with a compatible signature must exist, otherwise the link fails with an undefined symbol.

The attribute works on PROGRAM, FUNCTION, and FUNCTION_BLOCK.

Declarations from a file

-i includes a whole file as external. The compiler reads its declarations and ignores every body:

plc main.st -i vendor.st -L/opt/vendor/lib -lvendor -o app --linker=cc

Repeat -i for more files, and quote a pattern, so that the shell does not expand it into arguments that the compiler cannot read:

plc main.st -i "/usr/share/plc/include/*.st" -l iec61131std -o app --linker=cc

Call a C function

Give the C function a declaration in Structured Text. The signature must match what C expects.

int min(int a, int b);
{external}
FUNCTION min: DINT
    VAR_INPUT
        a: DINT;
        b: DINT;
    END_VAR
END_FUNCTION

The C interface chapter has the rules that turn a declaration into a C signature.

Variadic arguments

A parameter of type ... in the last VAR_INPUT block makes the function variadic, like printf in C.

{external}
FUNCTION printf: DINT
    VAR_INPUT {ref}
        format: STRING;
    END_VAR
    VAR_INPUT
        args: ...;
    END_VAR
END_FUNCTION

FUNCTION main: DINT
    VAR
        tmp: DINT;
    END_VAR

    tmp := 1;
    printf('Value %d, %d, %d$N', tmp, tmp * 10, tmp * 100);
    main := tmp;
END_FUNCTION
plc printer.st -o printer --linker=cc
./printer

There are three variadic forms, and they differ in what the callee receives:

FormWhat the callee gets
args: ...Every argument, then a null pointer after the last one
args: T...Every argument as a T, and nothing after them
args: {sized} T...The number of arguments, then a pointer to an array of T

The null pointer of the untyped form lets a callee that walks the list until a terminator always find the end, also when the call carries no variadic argument at all. A terminator that the caller writes ends the list first, so the added one stays unread. A callee that reads a fixed number of arguments, such as printf with its format string or a function with a count parameter, never sees the terminator.

The typed forms keep exactly the argument list of the caller, so their callees must not expect a terminator.

Note

Arguments of the untyped form follow the promotion rules of C: values smaller than 32 bits arrive as 32-bit values.

What’s next

A declaration must match what the other side expects. The next chapter gives the C type of every construct.