C++

This section describes the C++ specific language considerations.

Library properties

Library properties

Property

Value

Remarks

Language standard

C++17

For data type and function definitions. The pmpwrapper.cpp is functionally verified with the following compilers:

  • MSVC++ v142 (Visual Studio 2019)

  • GCC 10.3

Namespace

Pmp

To avoid name clashes, all data types are contained in their own namespace.

Library type

Shared library

Easier library updates, since the application does not have to be rebuilt when a library is updated, as long as its interface remains unchanged. Application makes use of a library via a wrapper.

Thread safety

Thread-safe and process-safe

All functions published by the library are thread-safe and process-safe, unless explicitly stated otherwise.

Notifications

Asynchronous

The application can subscribe to asynchronous notifications to be notified of certain events. Note that these callback functions can be called from any thread context.

Strings

UTF-8

All strings are UTF-8 encoded, unless explicitly stated otherwise.

Naming conventions

Naming conventions

Naming

Description

PXXX

A std::shared_ptr to interface IXXX or class CXXX.

IsXXX

A read-only boolean property accessor method.

ReserveXXX

Obtains a reference to a scarce resource where it is irrelevant to which instance a reference is obtained. Resources using this paradigm are not named and are not creatable nor configurable using XML controller configuration. The resource is released when all shared pointers to it go out-of-scope.

CreateXXX/Destroy

Obtains a reference to a dynamically created resource that does not exist when the controller is started. Resources using this paradigm are named and are creatable and configurable using XML controller configuration. The resource implements the IDestroyable interface to allow for destruction of the resource.

GetXXX

Obtains a reference to a resource that exists when the controller is started or a dynamically created resource. GetXXX is also used as a read property accessor method.

SetXXX

A write property accessor method.

SubscribeXXX

Registers a callback and outputs a subscription that is required to unsubscribe.

Lifetime and memory allocation

References to interfaces stay valid until the related system object goes out of scope unless explicitly stated otherwise.

The client application and motion API use std::shared_ptr objects to exchange interface and class pointers.

The motion API implementation allocates and owns memory for objects unless explicitly stated otherwise.

Collections

A dedicated ISignalCollection interface is defined that represents a collection of signals that the user application can manipulate. The order of signals in the collection is equal to the order in which they were added.

Callbacks

The motion API employs a callback mechanism which allows user applications to receive asynchronous notifications on the occurrence of events. User applications can register a function to receive a callback when a certain event occurs. Upon registration, an object implementing the ISubscription interface is returned which must be used to unsubscribe a registered function from receiving callbacks.

The motion API supports multiple callback functions to be subscribed for the same event. However, user applications can make no assumptions on the order in which subscribed functions are called.

Attention

Within callback functions it is not allowed to:

  • Call any function of the motion API.

  • Throw an exception. Exceptions thrown by a callback function are not handled by the motion API and cause an unhandled exception.

Attention

A callback blocks the execution of (parts of) the motion API. It is strongly recommended to carefully weigh which actions to execute from within callback context and which actions can be executed outside of the callback context. In general it is advised to let the callback return as quickly as possible.

A callback function must be provided in the form of an :std::function<...>. Since std::function can wrap free functions, member functions, lambda expressions as well as bind expressions, virtually any callable target can be used as callback function.

It is the responsibility of the user application to ensure the provided std::function remains callable while the callback is subscribed. This particularly applies when using std::bind to bind a (non-static) member function pointer to an object instance. To ensure that an object responsible for receiving a callback remains to exist, use either of the following approaches:

  • Wrap the object in an std::shared_ptr and use this shared pointer as the second argument of std::bind.

  • Wrap the object in an std::shared_ptr and use this shared pointer as the second argument of the helper function WeakBind. This approach is recommended when the subscription is stored within the object, which would create a circular reference when using std::bind.

The helper function WeakBind is provided to bind a member function pointer to an object instance, while only holding a weak reference to the object. The usage of WeakBind is equal to that of std::bind, except that the object which is bound must be owned by an std::shared_ptr.

WeakBind
1
2
3
4
5
6
template <class T, class R, class... Args, class... BoundArgs>
auto WeakBind(
  R(T::* memfunc)(Args...),
  std::weak_ptr<T> inst,
  BoundArgs... boundArgs) ->
    decltype(std::bind(std::function<R(Args...)>(), boundArgs...));

Error handling

The motion API handles errors by throwing exceptions of type CPmpException. Typical error handling lists how a user application would typically handle a certain exception.

Typical error handling

Exception

Response

CAbortedException

Retry command, ignore, or fail

CAccessDeniedException

Application error, provide a filename that can be opened for reading/writing

CChecksumErrorException

Either transfer failed, or source file corrupt; retry or fail

CCommunicationErrorException

Motion API implementation error, option to try again, but possible connection lost

CConnectionLostException

Controller connection was lost, reconnect to the controller and try again

CConnectionRefusedException

Initialization failure

CIncompatibleException

Older/newer motion API implementation required

CInvalidArgumentException

Application error, provide a valid argument

CInvalidConfigException

Application error, provide a valid configuration

CInvalidFormatException

Application error, provide contents in valid format

CInvalidOperationException

Application error, operation not possible in current state, option to change state and try again

CNotImplementedException

Requested function not implemented; not recoverable.

CNullArgumentException

Application error, provide a valid argument

CObjectDestroyedException

Requested function called on an object which is destroyed; not recoverable

COutOfResourcesException

Wait for resource to become available, option to clean up old unused resources

CReadErrorException

Retry or fail

CRebootedException

Controller was rebooted and connection was restored, retrieve the interface again and try again

CResourceBusyException

Wait for resource to become idle

CTimeoutException

Investigate reason or try with a larger timeout

CUnexpectedException

Motion API implementation error, report to Prodrive Technologies; not recoverable.

CUnknownObjectException

Application error, provide a correct object reference

CUnsupportedException

Application error, operation not possible (in any state)

CWriteErrorException

Out of (disk) space? Retry or fail