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