APIs, concepts, guides, and more
rttaskglobals.h
1#pragma once
2
3#ifndef RT_TASKS_GLOBALS_H
4#define RT_TASKS_GLOBALS_H
5
6#include <atomic> // For std::atomic
7#include <cstddef> // For std::size_t, offsetof
8#include <cstring> // For std::memset, std::strcmp
9#include <type_traits> // For std::is_same
10
11#include "rttask.h"
12
13
14#if defined(WIN32)
15 #define LIBRARY_EXPORT __declspec(dllexport)
16 #define LIBRARY_IMPORT __declspec(dllimport)
17#elif defined(__linux__)
18 #define LIBRARY_EXPORT __attribute__((visibility("default")))
19 #define LIBRARY_IMPORT __attribute__((visibility("default")))
20#else
21 #define LIBRARY_EXPORT
22 #define LIBRARY_IMPORT
23#endif // defined(WIN32) || defined(__linux__)
24
25#define NAME(name) name
26#define CONCAT(left, right) left ## right
27#define RSI_TASK(name) \
28 void CONCAT(name, Core)(RSI::RapidCode::RealTimeTasks::GlobalData*); \
29 extern "C" LIBRARY_EXPORT int32_t NAME(name)(RSI::RapidCode::RealTimeTasks::GlobalData* data, char* buffer, const uint32_t size) { return CallFunction(CONCAT(name, Core), data, buffer, size); } \
30 void CONCAT(name, Core)(RSI::RapidCode::RealTimeTasks::GlobalData* data)
31
32template<typename FunctionType>
33int32_t CallFunction(FunctionType&& func, RSI::RapidCode::RealTimeTasks::GlobalData* data, char* buffer, const uint32_t size)
34{
35 int32_t result = 0;
36 try
37 {
38 func(data);
39 }
40 catch(const std::exception& error)
41 {
42 result = -1;
43 std::snprintf(buffer, size, "%s", error.what());
44 }
45 catch(...)
46 {
47 result = -1;
48 std::snprintf(buffer, size, "Unknown error occurred in task.");
49 }
50 return result;
51}
52
53
54namespace RSI
55{
56namespace RapidCode
57{
58namespace RealTimeTasks
59{
60
61// Add global variables as data members of this struct using the RSI_GLOBAL macro.
62// Please use "plain-old data" types (POD), preferably sized ones, such as:
63// int32_t, uint32_t,
64// int64_t, uint64_t,
65// float, double,
66// char, bool,
67// Arrays of POD types are technically possible, but it will be difficult to access them from the RapidCode API.
69struct GlobalData
70{
71 GlobalData() { std::memset(this, 0, sizeof(*this)); }
72 GlobalData(GlobalData&& other) { std::memcpy(this, &other, sizeof(*this)); }
73
74 // A shared integer counter
75 RSI_GLOBAL(int64_t, counter);
76
77 // Shared values for FollowSensor
78 RSI_GLOBAL(int32_t, startingSample);
79 RSI_GLOBAL(double, sensorValue);
80};
81
82inline constexpr GlobalMetadataMap<RSI::RapidCode::RealTimeTasks::GlobalMaxSize> GlobalMetadata(
83{
84 REGISTER_GLOBAL(counter),
85 REGISTER_GLOBAL(startingSample),
86 REGISTER_GLOBAL(sensorValue),
87});
89
90extern "C"
91{
92 LIBRARY_EXPORT int32_t GlobalMemberOffsetGet(const char* const name)
93 {
94 return GlobalMetadata[name].offset;
95 }
96 static_assert(std::is_same<decltype(&GlobalMemberOffsetGet), GlobalMemberOffsetGetter>::value, "GlobalMemberOffsetGet function signature does not match GlobalMemberOffsetGetter type.");
97
98 LIBRARY_EXPORT int32_t GlobalNamesFill(const char* names[], int32_t capacity)
99 {
100 int32_t index = 0;
101 for (; index < GlobalMetadata.Size() && index < capacity; ++index)
102 {
103 names[index] = GlobalMetadata[index].key;
104 }
105 return index;
106 }
107 static_assert(std::is_same<decltype(&GlobalNamesFill), GlobalNamesGetter>::value, "GlobalNamesGet function signature does not match GlobalNamesGetter type.");
108
109 LIBRARY_EXPORT std::int32_t GlobalMemberTypeGet(const char* const name)
110 {
111 return static_cast<std::int32_t>(GlobalMetadata[name].type);
112 }
113 static_assert(std::is_same<decltype(&GlobalMemberTypeGet), GlobalMemberTypeGetter>::value, "GlobalMemberTypeGet function signature does not match GlobalMemberTypeGetter type.");
114}
115
116static_assert(sizeof(GlobalData) <= RSI::RapidCode::RealTimeTasks::GlobalMaxSize, "GlobalData struct is too large.");
117
118} // end namespace RealTimeTasks
119} // end namespace RapidCode
120} // end namespace RSI
121
122extern "C"
123{
124 LIBRARY_IMPORT RSI::RapidCode::MotionController* MotionControllerGet(char* errorBuffer, const uint32_t errorBufferSize);
125 LIBRARY_IMPORT RSI::RapidCode::Axis* AxisGet(const int32_t axisIndex, char* errorBuffer, const uint32_t errorBufferSize);
126 LIBRARY_IMPORT RSI::RapidCode::RapidCodeNetworkNode* NetworkNodeGet(const int32_t index, char* errorBuffer, const uint32_t errorBufferSize);
127 LIBRARY_IMPORT RSI::RapidCode::MultiAxis* MultiAxisGet(const int32_t index, char* errorBuffer, const uint32_t errorBufferSize);
128}
129
130template<typename FunctionType, typename ... Args>
131auto RTObjectGet(FunctionType&& func, Args&& ... args)
132{
133 char errorBuffer[256] = {};
134 auto object = std::forward<FunctionType>(func)(std::forward<Args>(args)..., errorBuffer, sizeof(errorBuffer));
135 if (object == nullptr) { throw std::runtime_error(errorBuffer); };
136 return object;
137}
138inline auto RTMotionControllerGet() { return RTObjectGet(MotionControllerGet); }
139inline auto RTAxisGet(const int32_t index) { return RTObjectGet(AxisGet, index); }
140inline auto RTMultiAxisGet(const int32_t index) { return RTObjectGet(MultiAxisGet, index); }
141inline auto RTNetworkNodeGet(const int32_t index) { return RTObjectGet(NetworkNodeGet, index); }
142
143#endif // !defined(RT_TASKS_GLOBALS_H)
Represents a single axis of motion control. This class provides an interface for commanding motion,...
Definition rsi.h:5921
Represents the RMP soft motion controller. This class provides an interface to general controller con...
Definition rsi.h:800
Represents multiple axes of motion control, allows you to map two or more Axis objects together for e...
Definition rsi.h:10842
The RealTimeTasks namespace.
Definition rttask.h:36
LIBRARY_EXPORT int32_t GlobalMemberOffsetGet(const char *const name)
@[RTTasksGlobalData]