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 double variables
78 RSI_GLOBAL(double, average);
79};
80
81inline constexpr GlobalMetadataMap<RSI::RapidCode::RealTimeTasks::GlobalMaxSize> GlobalMetadata(
82{
83 REGISTER_GLOBAL(counter),
84 REGISTER_GLOBAL(average),
85});
87
88extern "C"
89{
90 LIBRARY_EXPORT int32_t GlobalMemberOffsetGet(const char* const name)
91 {
92 return GlobalMetadata[name].offset;
93 }
94 static_assert(std::is_same<decltype(&GlobalMemberOffsetGet), GlobalMemberOffsetGetter>::value, "GlobalMemberOffsetGet function signature does not match GlobalMemberOffsetGetter type.");
95
96 LIBRARY_EXPORT int32_t GlobalNamesFill(const char* names[], int32_t capacity)
97 {
98 int32_t index = 0;
99 for (; index < GlobalMetadata.Size() && index < capacity; ++index)
100 {
101 names[index] = GlobalMetadata[index].key;
102 }
103 return index;
104 }
105 static_assert(std::is_same<decltype(&GlobalNamesFill), GlobalNamesGetter>::value, "GlobalNamesGet function signature does not match GlobalNamesGetter type.");
106
107 LIBRARY_EXPORT std::int32_t GlobalMemberTypeGet(const char* const name)
108 {
109 return static_cast<std::int32_t>(GlobalMetadata[name].type);
110 }
111 static_assert(std::is_same<decltype(&GlobalMemberTypeGet), GlobalMemberTypeGetter>::value, "GlobalMemberTypeGet function signature does not match GlobalMemberTypeGetter type.");
112}
113
114static_assert(sizeof(GlobalData) <= RSI::RapidCode::RealTimeTasks::GlobalMaxSize, "GlobalData struct is too large.");
115
116} // end namespace RealTimeTasks
117} // end namespace RapidCode
118} // end namespace RSI
119
120extern "C"
121{
122 LIBRARY_IMPORT RSI::RapidCode::MotionController* MotionControllerGet(char* errorBuffer, const uint32_t errorBufferSize);
123 LIBRARY_IMPORT RSI::RapidCode::Axis* AxisGet(const int32_t axisIndex, char* errorBuffer, const uint32_t errorBufferSize);
124 LIBRARY_IMPORT RSI::RapidCode::RapidCodeNetworkNode* NetworkNodeGet(const int32_t index, char* errorBuffer, const uint32_t errorBufferSize);
125 LIBRARY_IMPORT RSI::RapidCode::MultiAxis* MultiAxisGet(const int32_t index, char* errorBuffer, const uint32_t errorBufferSize);
126}
127
128template<typename FunctionType, typename ... Args>
129auto RTObjectGet(FunctionType&& func, Args&& ... args)
130{
131 char errorBuffer[256] = {};
132 auto object = std::forward<FunctionType>(func)(std::forward<Args>(args)..., errorBuffer, sizeof(errorBuffer));
133 if (object == nullptr) { throw std::runtime_error(errorBuffer); };
134 return object;
135}
136inline auto RTMotionControllerGet() { return RTObjectGet(MotionControllerGet); }
137inline auto RTAxisGet(const int32_t index) { return RTObjectGet(AxisGet, index); }
138inline auto RTMultiAxisGet(const int32_t index) { return RTObjectGet(MultiAxisGet, index); }
139inline auto RTNetworkNodeGet(const int32_t index) { return RTObjectGet(NetworkNodeGet, index); }
140
141#endif // !defined(RT_TASKS_GLOBALS_H)
Represents a single axis of motion control. This class provides an interface for commanding motion,...
Definition rsi.h:5863
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:10795
The RealTimeTasks namespace.
Definition rttask.h:36
LIBRARY_EXPORT int32_t GlobalMemberOffsetGet(const char *const name)
@[RTTasksGlobalData]