Compare commits

..

4 Commits

Author SHA1 Message Date
2f8ae23d57 Added static cast to force correct type 2025-06-16 16:15:24 +02:00
603b3e77af Revised version with adapted macros 2025-06-16 15:53:36 +02:00
31ff26cb78 Generalized getAxisParam 2025-06-16 15:24:28 +02:00
43df40aaea WIP 2025-06-16 13:32:49 +02:00
2 changed files with 139 additions and 96 deletions

View File

@@ -10,6 +10,8 @@
#include <math.h> #include <math.h>
#include <unistd.h> #include <unistd.h>
#define getControllerMethod pController
struct sinqAxisImpl { struct sinqAxisImpl {
// Internal variables used in the movement timeout watchdog // Internal variables used in the movement timeout watchdog
time_t expectedArrivalTime; time_t expectedArrivalTime;
@@ -28,21 +30,23 @@ struct sinqAxisImpl {
epicsTimeStamp lastPollTime; epicsTimeStamp lastPollTime;
}; };
template <typename T> struct TypeTag {};
// Generic fallback - if the compiler tries to compile this function, it fails. // Generic fallback - if the compiler tries to compile this function, it fails.
template <typename T> template <typename A, typename C, typename T>
asynStatus setAxisParam(sinqAxis *axis, const char *indexName, asynStatus setAxisParamImpl(A *axis, C *controller, const char *indexName,
int (sinqController::*func)(), T writeValue, int (C::*func)(), T writeValue,
const char *callerFunctionName, int lineNumber) { const char *callerFunctionName, int lineNumber,
static_assert( TypeTag<void>) {
sizeof(T) == 0, static_assert(sizeof(T) == 0, "Unsupported type for setAxisParamImpl");
"no specialization of setAxisParam exists for the given type");
return asynError; return asynError;
} }
template <> template <typename A, typename C>
asynStatus setAxisParam<int>(sinqAxis *axis, const char *indexName, asynStatus setAxisParamImpl(A *axis, C *controller, const char *indexName,
int (sinqController::*func)(), int writeValue, int (C::*func)(), int writeValue,
const char *callerFunctionName, int lineNumber) { const char *callerFunctionName, int lineNumber,
TypeTag<int>) {
int indexValue = (axis->pController()->*func)(); int indexValue = (axis->pController()->*func)();
asynStatus status = axis->setIntegerParam(indexValue, writeValue); asynStatus status = axis->setIntegerParam(indexValue, writeValue);
if (status != asynSuccess) { if (status != asynSuccess) {
@@ -52,19 +56,21 @@ asynStatus setAxisParam<int>(sinqAxis *axis, const char *indexName,
return asynSuccess; return asynSuccess;
} }
template <> template <typename A, typename C>
asynStatus setAxisParam<bool>(sinqAxis *axis, const char *indexName, asynStatus setAxisParamImpl(A *axis, C *controller, const char *indexName,
int (sinqController::*func)(), bool writeValue, int (C::*func)(), bool writeValue,
const char *callerFunctionName, int lineNumber) { const char *callerFunctionName, int lineNumber,
return setAxisParam(axis, indexName, func, static_cast<int>(writeValue), TypeTag<bool>) {
callerFunctionName, lineNumber); return setAxisParamImpl(axis, controller, indexName, func,
static_cast<int>(writeValue), callerFunctionName,
lineNumber, TypeTag<int>{});
} }
template <> template <typename A, typename C>
asynStatus asynStatus setAxisParamImpl(A *axis, C *controller, const char *indexName,
setAxisParam<double>(sinqAxis *axis, const char *indexName,
int (sinqController::*func)(), double writeValue, int (sinqController::*func)(), double writeValue,
const char *callerFunctionName, int lineNumber) { const char *callerFunctionName, int lineNumber,
TypeTag<double>) {
int indexValue = (axis->pController()->*func)(); int indexValue = (axis->pController()->*func)();
asynStatus status = axis->setDoubleParam(indexValue, writeValue); asynStatus status = axis->setDoubleParam(indexValue, writeValue);
if (status != asynSuccess) { if (status != asynSuccess) {
@@ -74,11 +80,11 @@ setAxisParam<double>(sinqAxis *axis, const char *indexName,
return asynSuccess; return asynSuccess;
} }
template <> template <typename A, typename C>
asynStatus setAxisParam<char *>(sinqAxis *axis, const char *indexName, asynStatus setAxisParamImpl(A *axis, C *controller, const char *indexName,
int (sinqController::*func)(), char *writeValue, int (C::*func)(), char *writeValue,
const char *callerFunctionName, const char *callerFunctionName, int lineNumber,
int lineNumber) { TypeTag<char *>) {
int indexValue = (axis->pController()->*func)(); int indexValue = (axis->pController()->*func)();
asynStatus status = axis->setStringParam(indexValue, writeValue); asynStatus status = axis->setStringParam(indexValue, writeValue);
if (status != asynSuccess) { if (status != asynSuccess) {
@@ -88,12 +94,11 @@ asynStatus setAxisParam<char *>(sinqAxis *axis, const char *indexName,
return asynSuccess; return asynSuccess;
} }
template <> template <typename A, typename C>
asynStatus setAxisParam<const char *>(sinqAxis *axis, const char *indexName, asynStatus setAxisParamImpl(A *axis, C *controller, const char *indexName,
int (sinqController::*func)(), int (C::*func)(), const char *writeValue,
const char *writeValue, const char *callerFunctionName, int lineNumber,
const char *callerFunctionName, TypeTag<const char *>) {
int lineNumber) {
int indexValue = (axis->pController()->*func)(); int indexValue = (axis->pController()->*func)();
asynStatus status = axis->setStringParam(indexValue, writeValue); asynStatus status = axis->setStringParam(indexValue, writeValue);
if (status != asynSuccess) { if (status != asynSuccess) {
@@ -103,21 +108,31 @@ asynStatus setAxisParam<const char *>(sinqAxis *axis, const char *indexName,
return asynSuccess; return asynSuccess;
} }
template <typename A, typename C, typename T>
asynStatus setAxisParam(A *axis, C *controller, const char *indexName,
int (C::*func)(), T writeValue,
const char *callerFunctionName, int lineNumber) {
return setAxisParamImpl(axis, controller, indexName, func, writeValue,
callerFunctionName, lineNumber, TypeTag<T>{});
}
// Generic fallback - if the compiler tries to compile this function, it fails. // Generic fallback - if the compiler tries to compile this function, it fails.
template <typename T> template <typename A, typename C, typename T>
asynStatus getAxisParam(sinqAxis *axis, const char *indexName, asynStatus getAxisParamImpl(A *axis, C *controller, const char *indexName,
int (sinqController::*func)(), T *readValue, int (C::*func)(), T *readValue,
const char *callerFunctionName, int lineNumber) { const char *callerFunctionName, int lineNumber,
TypeTag<void>) {
static_assert( static_assert(
sizeof(T) == 0, sizeof(T) == 0,
"no specialization of getAxisParam exists for the given type"); "no specialization of getAxisParam exists for the given type");
return asynError; return asynError;
} }
template <> template <typename A, typename C>
asynStatus getAxisParam<int>(sinqAxis *axis, const char *indexName, asynStatus getAxisParamImpl(A *axis, C *controller, const char *indexName,
int (sinqController::*func)(), int *readValue, int (C::*func)(), int *readValue,
const char *callerFunctionName, int lineNumber) { const char *callerFunctionName, int lineNumber,
TypeTag<int>) {
int indexValue = (axis->pController()->*func)(); int indexValue = (axis->pController()->*func)();
asynStatus status = axis->pController()->getIntegerParam( asynStatus status = axis->pController()->getIntegerParam(
axis->axisNo(), indexValue, readValue); axis->axisNo(), indexValue, readValue);
@@ -128,19 +143,20 @@ asynStatus getAxisParam<int>(sinqAxis *axis, const char *indexName,
return asynSuccess; return asynSuccess;
} }
template <> template <typename A, typename C>
asynStatus getAxisParam<bool>(sinqAxis *axis, const char *indexName, asynStatus getAxisParamImpl(A *axis, C *controller, const char *indexName,
int (sinqController::*func)(), bool *readValue, int (C::*func)(), bool *readValue,
const char *callerFunctionName, int lineNumber) { const char *callerFunctionName, int lineNumber,
return getAxisParam(axis, indexName, func, (int *)readValue, TypeTag<bool>) {
return getAxisParamImpl(axis, indexName, func, (int *)readValue,
callerFunctionName, lineNumber); callerFunctionName, lineNumber);
} }
template <> template <typename A, typename C>
asynStatus asynStatus getAxisParamImpl(A *axis, C *controller, const char *indexName,
getAxisParam<double>(sinqAxis *axis, const char *indexName, int (C::*func)(), double *readValue,
int (sinqController::*func)(), double *readValue, const char *callerFunctionName, int lineNumber,
const char *callerFunctionName, int lineNumber) { TypeTag<double>) {
int indexValue = (axis->pController()->*func)(); int indexValue = (axis->pController()->*func)();
asynStatus status = axis->pController()->getDoubleParam( asynStatus status = axis->pController()->getDoubleParam(
axis->axisNo(), indexValue, readValue); axis->axisNo(), indexValue, readValue);
@@ -151,10 +167,11 @@ getAxisParam<double>(sinqAxis *axis, const char *indexName,
return asynSuccess; return asynSuccess;
} }
template <> template <typename A, typename C>
asynStatus getAxisParam<char>(sinqAxis *axis, const char *indexName, asynStatus getAxisParamImpl(A *axis, C *controller, const char *indexName,
int (sinqController::*func)(), char *readValue, int (C::*func)(), char *readValue,
const char *callerFunctionName, int lineNumber) { const char *callerFunctionName, int lineNumber,
TypeTag<char>) {
int maxChars = 200; int maxChars = 200;
@@ -168,21 +185,22 @@ asynStatus getAxisParam<char>(sinqAxis *axis, const char *indexName,
return asynSuccess; return asynSuccess;
} }
template <size_t N> template <typename A, typename C, size_t N>
asynStatus getAxisParam(sinqAxis *axis, const char *indexName, asynStatus getAxisParamImpl(A *axis, C *controller, const char *indexName,
int (sinqController::*func)(), char (&readValue)[N], int (C::*func)(), char (&readValue)[N],
const char *callerFunctionName, int lineNumber) { const char *callerFunctionName, int lineNumber,
TypeTag<char>) {
// Decay the array to char* // Decay the array to char*
return getAxisParam<char>(axis, indexName, func, return getAxisParamImpl(axis, controller, indexName, func,
static_cast<char *>(readValue), static_cast<char *>(readValue), callerFunctionName,
callerFunctionName, lineNumber); lineNumber);
} }
template <> template <typename A, typename C>
asynStatus asynStatus getAxisParamImpl(A *axis, C *controller, const char *indexName,
getAxisParam<std::string>(sinqAxis *axis, const char *indexName, int (C::*func)(), std::string *readValue,
int (sinqController::*func)(), std::string *readValue, const char *callerFunctionName, int lineNumber,
const char *callerFunctionName, int lineNumber) { TypeTag<std::string>) {
int indexValue = (axis->pController()->*func)(); int indexValue = (axis->pController()->*func)();
// Convert the pointer to a reference, since getStringParam expects the // Convert the pointer to a reference, since getStringParam expects the
@@ -198,6 +216,14 @@ getAxisParam<std::string>(sinqAxis *axis, const char *indexName,
return asynSuccess; return asynSuccess;
} }
template <typename A, typename C, typename T>
asynStatus getAxisParam(A *axis, C *controller, const char *indexName,
int (C::*func)(), std::string *readValue,
const char *callerFunctionName, int lineNumber) {
return getAxisParamImpl(axis, controller, indexName, func, readValue,
callerFunctionName, lineNumber, TypeTag<T>{});
}
// ============================================================================= // =============================================================================
sinqAxis::sinqAxis(class sinqController *pC, int axisNo) sinqAxis::sinqAxis(class sinqController *pC, int axisNo)

View File

@@ -365,9 +365,22 @@ class epicsShareClass sinqAxis : public asynMotorAxis {
asynStatus assertConnected(); asynStatus assertConnected();
/** /**
* @brief Return a pointer to the axis controller * @brief Return a pointer to the axis controller.
*
* This function should be overriden in derived classes using the `override`
* keyword so the macros `getAxisParamChecked` and `setAxisParamChecked`
* work correctly:
*
* ```
* class mySpecialAxis : public sinqAxis {
public:
mySpecialController* getControllerMethod() override {
return mySpecialControllerPtr;
}
};
* ```
*/ */
sinqController *pController() { return pC_; }; virtual sinqController *pController() { return pC_; };
/** /**
* @brief Returns true, if the axis was moving in the last poll cycle, and * @brief Returns true, if the axis was moving in the last poll cycle, and
@@ -423,9 +436,9 @@ class epicsShareClass sinqAxis : public asynMotorAxis {
* @param lineNumber * @param lineNumber
* @return asynStatus * @return asynStatus
*/ */
template <typename T> template <typename A, typename C, typename T>
asynStatus setAxisParam(sinqAxis *axis, const char *indexName, asynStatus setAxisParam(A *axis, C *controller, const char *indexName,
int (sinqController::*func)(), T writeValue, int (C::*func)(), T writeValue,
const char *callerFunctionName, int lineNumber); const char *callerFunctionName, int lineNumber);
/** /**
@@ -454,17 +467,19 @@ asynStatus setAxisParam(sinqAxis *axis, const char *indexName,
* ``` * ```
* ============================================================================= * =============================================================================
*/ */
#define setAxisParamChecked(axis, indexGetterFunction, writeValue) \ #define setAxisParamChecked(axis, indexSetterFunction, writeValue) \
{ \ do { \
asynStatus setStatus = setAxisParam( \ auto *ctrlPtr = (axis)->pController(); \
axis, #indexGetterFunction, \ using ControllerType = \
&std::remove_pointer< \ typename std::remove_pointer<decltype(ctrlPtr)>::type; \
decltype(axis->pController())>::type::indexGetterFunction, \ asynStatus setStatus = \
setAxisParam(axis, ctrlPtr, #indexSetterFunction, \
static_cast<int (ControllerType::*)()>( \
&ControllerType::indexSetterFunction), \
writeValue, __PRETTY_FUNCTION__, __LINE__); \ writeValue, __PRETTY_FUNCTION__, __LINE__); \
if (setStatus != asynSuccess) { \ if (setStatus != asynSuccess) \
return setStatus; \ return setStatus; \
} \ } while (0)
}
// ============================================================================= // =============================================================================
// Helper functions and definitions for the macro getAxisParamChecked // Helper functions and definitions for the macro getAxisParamChecked
@@ -488,9 +503,9 @@ asynStatus setAxisParam(sinqAxis *axis, const char *indexName,
* to. * to.
* @return asynStatus * @return asynStatus
*/ */
template <typename T> template <typename A, typename C, typename T>
asynStatus getAxisParam(sinqAxis *axis, const char *indexName, asynStatus getAxisParam(A *axis, C *controller, const char *indexName,
int (sinqController::*func)(), T *readValue, int (C::*func)(), T *readValue,
const char *callerFunctionName, int lineNumber); const char *callerFunctionName, int lineNumber);
/** /**
@@ -498,7 +513,7 @@ asynStatus getAxisParam(sinqAxis *axis, const char *indexName,
* *
* This macro is a wrapper around `getIntegerParam` / `getDoubleParam` / * This macro is a wrapper around `getIntegerParam` / `getDoubleParam` /
* `getStringParam` which checks if the operation was successfull. If it wasn't, * `getStringParam` which checks if the operation was successfull. If it wasn't,
* it returns by calling the paramLibAccessFailed function. * it returns by calling the paramLibAccessFailed function. In order
* *
* For example, the following input: * For example, the following input:
* ``` * ```
@@ -520,15 +535,17 @@ asynStatus getAxisParam(sinqAxis *axis, const char *indexName,
* ============================================================================= * =============================================================================
*/ */
#define getAxisParamChecked(axis, indexGetterFunction, readValue) \ #define getAxisParamChecked(axis, indexGetterFunction, readValue) \
{ \ do { \
asynStatus getStatus = getAxisParam( \ auto *ctrlPtr = (axis)->pController(); \
axis, #indexGetterFunction, \ using ControllerType = \
&std::remove_pointer< \ typename std::remove_pointer<decltype(ctrlPtr)>::type; \
decltype(axis->pController())>::type::indexGetterFunction, \ asynStatus getStatus = \
getAxisParam(axis, ctrlPtr, #indexGetterFunction, \
static_cast<int (ControllerType::*)()>( \
&ControllerType::indexGetterFunction), \
readValue, __PRETTY_FUNCTION__, __LINE__); \ readValue, __PRETTY_FUNCTION__, __LINE__); \
if (getStatus != asynSuccess) { \ if (getStatus != asynSuccess) \
return getStatus; \ return getStatus; \
} \ } while (0)
}
#endif #endif