From 3d984f26bc6600a8c708c102213a004367a7bd7d Mon Sep 17 00:00:00 2001 From: smathis Date: Tue, 17 Jun 2025 08:33:18 +0200 Subject: [PATCH] Moved template functions to header to avoid linker errors --- src/sinqAxis.cpp | 196 ------------------------------------------ src/sinqAxis.h | 200 +++++++++++++++++++++++++++++++++++++++++-- src/sinqController.h | 14 ++- 3 files changed, 203 insertions(+), 207 deletions(-) diff --git a/src/sinqAxis.cpp b/src/sinqAxis.cpp index e12fa84..06cd0a5 100644 --- a/src/sinqAxis.cpp +++ b/src/sinqAxis.cpp @@ -30,202 +30,6 @@ struct sinqAxisImpl { epicsTimeStamp lastPollTime; }; -template struct TypeTag {}; - -// Generic fallback - if the compiler tries to compile this function, it fails. -template -asynStatus setAxisParamImpl(A *axis, C *controller, const char *indexName, - int (C::*func)(), T writeValue, - const char *callerFunctionName, int lineNumber, - TypeTag) { - static_assert(sizeof(T) == 0, "Unsupported type for setAxisParamImpl"); - return asynError; -} - -template -asynStatus setAxisParamImpl(A *axis, C *controller, const char *indexName, - int (C::*func)(), int writeValue, - const char *callerFunctionName, int lineNumber, - TypeTag) { - int indexValue = (axis->pController()->*func)(); - asynStatus status = axis->setIntegerParam(indexValue, writeValue); - if (status != asynSuccess) { - return axis->pController()->paramLibAccessFailed( - status, indexName, axis->axisNo(), callerFunctionName, lineNumber); - } - return asynSuccess; -} - -template -asynStatus setAxisParamImpl(A *axis, C *controller, const char *indexName, - int (C::*func)(), bool writeValue, - const char *callerFunctionName, int lineNumber, - TypeTag) { - return setAxisParamImpl(axis, controller, indexName, func, - static_cast(writeValue), callerFunctionName, - lineNumber, TypeTag{}); -} - -template -asynStatus setAxisParamImpl(A *axis, C *controller, const char *indexName, - int (sinqController::*func)(), double writeValue, - const char *callerFunctionName, int lineNumber, - TypeTag) { - int indexValue = (axis->pController()->*func)(); - asynStatus status = axis->setDoubleParam(indexValue, writeValue); - if (status != asynSuccess) { - return axis->pController()->paramLibAccessFailed( - status, indexName, axis->axisNo(), callerFunctionName, lineNumber); - } - return asynSuccess; -} - -template -asynStatus setAxisParamImpl(A *axis, C *controller, const char *indexName, - int (C::*func)(), char *writeValue, - const char *callerFunctionName, int lineNumber, - TypeTag) { - int indexValue = (axis->pController()->*func)(); - asynStatus status = axis->setStringParam(indexValue, writeValue); - if (status != asynSuccess) { - return axis->pController()->paramLibAccessFailed( - status, indexName, axis->axisNo(), callerFunctionName, lineNumber); - } - return asynSuccess; -} - -template -asynStatus setAxisParamImpl(A *axis, C *controller, const char *indexName, - int (C::*func)(), const char *writeValue, - const char *callerFunctionName, int lineNumber, - TypeTag) { - int indexValue = (axis->pController()->*func)(); - asynStatus status = axis->setStringParam(indexValue, writeValue); - if (status != asynSuccess) { - return axis->pController()->paramLibAccessFailed( - status, indexName, axis->axisNo(), callerFunctionName, lineNumber); - } - return asynSuccess; -} - -template -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{}); -} - -// Generic fallback - if the compiler tries to compile this function, it fails. -template -asynStatus getAxisParamImpl(A *axis, C *controller, const char *indexName, - int (C::*func)(), T *readValue, - const char *callerFunctionName, int lineNumber, - TypeTag) { - static_assert( - sizeof(T) == 0, - "no specialization of getAxisParam exists for the given type"); - return asynError; -} - -template -asynStatus getAxisParamImpl(A *axis, C *controller, const char *indexName, - int (C::*func)(), int *readValue, - const char *callerFunctionName, int lineNumber, - TypeTag) { - int indexValue = (axis->pController()->*func)(); - asynStatus status = axis->pController()->getIntegerParam( - axis->axisNo(), indexValue, readValue); - if (status != asynSuccess) { - return axis->pController()->paramLibAccessFailed( - status, indexName, axis->axisNo(), callerFunctionName, lineNumber); - } - return asynSuccess; -} - -template -asynStatus getAxisParamImpl(A *axis, C *controller, const char *indexName, - int (C::*func)(), bool *readValue, - const char *callerFunctionName, int lineNumber, - TypeTag) { - return getAxisParamImpl(axis, indexName, func, (int *)readValue, - callerFunctionName, lineNumber); -} - -template -asynStatus getAxisParamImpl(A *axis, C *controller, const char *indexName, - int (C::*func)(), double *readValue, - const char *callerFunctionName, int lineNumber, - TypeTag) { - int indexValue = (axis->pController()->*func)(); - asynStatus status = axis->pController()->getDoubleParam( - axis->axisNo(), indexValue, readValue); - if (status != asynSuccess) { - return axis->pController()->paramLibAccessFailed( - status, indexName, axis->axisNo(), callerFunctionName, lineNumber); - } - return asynSuccess; -} - -template -asynStatus getAxisParamImpl(A *axis, C *controller, const char *indexName, - int (C::*func)(), char *readValue, - const char *callerFunctionName, int lineNumber, - TypeTag) { - - int maxChars = 200; - - int indexValue = (axis->pController()->*func)(); - asynStatus status = axis->pController()->getStringParam( - axis->axisNo(), indexValue, maxChars, readValue); - if (status != asynSuccess) { - return axis->pController()->paramLibAccessFailed( - status, indexName, axis->axisNo(), callerFunctionName, lineNumber); - } - return asynSuccess; -} - -template -asynStatus getAxisParamImpl(A *axis, C *controller, const char *indexName, - int (C::*func)(), char (&readValue)[N], - const char *callerFunctionName, int lineNumber, - TypeTag) { - // Decay the array to char* - return getAxisParamImpl(axis, controller, indexName, func, - static_cast(readValue), callerFunctionName, - lineNumber); -} - -template -asynStatus getAxisParamImpl(A *axis, C *controller, const char *indexName, - int (C::*func)(), std::string *readValue, - const char *callerFunctionName, int lineNumber, - TypeTag) { - int indexValue = (axis->pController()->*func)(); - - // Convert the pointer to a reference, since getStringParam expects the - // latter. - std::string &rReadValue = *readValue; - - asynStatus status = axis->pController()->getStringParam( - axis->axisNo(), indexValue, rReadValue); - if (status != asynSuccess) { - return axis->pController()->paramLibAccessFailed( - status, indexName, axis->axisNo(), callerFunctionName, lineNumber); - } - return asynSuccess; -} - -template -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{}); -} - -// ============================================================================= - sinqAxis::sinqAxis(class sinqController *pC, int axisNo) : asynMotorAxis((asynMotorController *)pC, axisNo), pC_(pC) { asynStatus status = asynSuccess; diff --git a/src/sinqAxis.h b/src/sinqAxis.h index 68f4cf3..5347ed1 100644 --- a/src/sinqAxis.h +++ b/src/sinqAxis.h @@ -420,6 +420,84 @@ class epicsShareClass sinqAxis : public asynMotorAxis { // ============================================================================= // Helper functions and definitions for the macro setAxisParamChecked +template struct TypeTag {}; + +// Generic fallback - if the compiler tries to compile this function, it fails. +template +asynStatus setAxisParamImpl(A *axis, C *controller, const char *indexName, + int (C::*func)(), T writeValue, + const char *callerFunctionName, int lineNumber, + TypeTag) { + static_assert(sizeof(T) == 0, "Unsupported type for setAxisParamImpl"); + return asynError; +} + +template +asynStatus setAxisParamImpl(A *axis, C *controller, const char *indexName, + int (C::*func)(), int writeValue, + const char *callerFunctionName, int lineNumber, + TypeTag) { + int indexValue = (controller->*func)(); + asynStatus status = axis->setIntegerParam(indexValue, writeValue); + if (status != asynSuccess) { + return controller->paramLibAccessFailed( + status, indexName, axis->axisNo(), callerFunctionName, lineNumber); + } + return asynSuccess; +} + +template +asynStatus setAxisParamImpl(A *axis, C *controller, const char *indexName, + int (C::*func)(), bool writeValue, + const char *callerFunctionName, int lineNumber, + TypeTag) { + return setAxisParamImpl(axis, controller, indexName, func, + static_cast(writeValue), callerFunctionName, + lineNumber, TypeTag{}); +} + +template +asynStatus setAxisParamImpl(A *axis, C *controller, const char *indexName, + int (sinqController::*func)(), double writeValue, + const char *callerFunctionName, int lineNumber, + TypeTag) { + int indexValue = (controller->*func)(); + asynStatus status = axis->setDoubleParam(indexValue, writeValue); + if (status != asynSuccess) { + return controller->paramLibAccessFailed( + status, indexName, axis->axisNo(), callerFunctionName, lineNumber); + } + return asynSuccess; +} + +template +asynStatus setAxisParamImpl(A *axis, C *controller, const char *indexName, + int (C::*func)(), char *writeValue, + const char *callerFunctionName, int lineNumber, + TypeTag) { + int indexValue = (controller->*func)(); + asynStatus status = axis->setStringParam(indexValue, writeValue); + if (status != asynSuccess) { + return controller->paramLibAccessFailed( + status, indexName, axis->axisNo(), callerFunctionName, lineNumber); + } + return asynSuccess; +} + +template +asynStatus setAxisParamImpl(A *axis, C *controller, const char *indexName, + int (C::*func)(), const char *writeValue, + const char *callerFunctionName, int lineNumber, + TypeTag) { + int indexValue = (controller->*func)(); + asynStatus status = axis->setStringParam(indexValue, writeValue); + if (status != asynSuccess) { + return controller->paramLibAccessFailed( + status, indexName, axis->axisNo(), callerFunctionName, lineNumber); + } + return asynSuccess; +} + /** * @brief Helper function to set an integer / double / string parameter for an * axis in the paramLib @@ -429,6 +507,7 @@ class epicsShareClass sinqAxis : public asynMotorAxis { * * @tparam T * @param axis + * @param controller * @param indexName * @param func * @param writeValue @@ -439,7 +518,10 @@ class epicsShareClass sinqAxis : public asynMotorAxis { template asynStatus setAxisParam(A *axis, C *controller, const char *indexName, int (C::*func)(), T writeValue, - const char *callerFunctionName, int lineNumber); + const char *callerFunctionName, int lineNumber) { + return setAxisParamImpl(axis, controller, indexName, func, writeValue, + callerFunctionName, lineNumber, TypeTag{}); +} /** * @brief Macro to set an paramLib parameter and error checking the return value @@ -455,10 +537,10 @@ asynStatus setAxisParam(A *axis, C *controller, const char *indexName, * expands into the following code: * ``` * { - * int indexValue = axis->pController()->motorStatusProblem_(); + * int indexValue = controller->motorStatusProblem_(); * asynStatus status = axis->setIntegerParam(indexValue, writeValue); * if (status != asynSuccess) { - * return axis->pController()->paramLibAccessFailed( + * return controller->paramLibAccessFailed( * status, "motorStatusProblem_", axis->axisNo(), __PRETTY_FUNCTION__, * __LINE__); * } @@ -484,6 +566,104 @@ asynStatus setAxisParam(A *axis, C *controller, const char *indexName, // ============================================================================= // Helper functions and definitions for the macro getAxisParamChecked +// Generic fallback - if the compiler tries to compile this function, it fails. +template +asynStatus getAxisParamImpl(A *axis, C *controller, const char *indexName, + int (C::*func)(), T *readValue, + const char *callerFunctionName, int lineNumber, + TypeTag) { + static_assert( + sizeof(T) == 0, + "no specialization of getAxisParam exists for the given type"); + return asynError; +} + +template +asynStatus getAxisParamImpl(A *axis, C *controller, const char *indexName, + int (C::*func)(), int *readValue, + const char *callerFunctionName, int lineNumber, + TypeTag) { + int indexValue = (controller->*func)(); + asynStatus status = + controller->getIntegerParam(axis->axisNo(), indexValue, readValue); + if (status != asynSuccess) { + return controller->paramLibAccessFailed( + status, indexName, axis->axisNo(), callerFunctionName, lineNumber); + } + return asynSuccess; +} + +template +asynStatus getAxisParamImpl(A *axis, C *controller, const char *indexName, + int (C::*func)(), bool *readValue, + const char *callerFunctionName, int lineNumber, + TypeTag) { + return getAxisParamImpl(axis, indexName, func, (int *)readValue, + callerFunctionName, lineNumber); +} + +template +asynStatus getAxisParamImpl(A *axis, C *controller, const char *indexName, + int (C::*func)(), double *readValue, + const char *callerFunctionName, int lineNumber, + TypeTag) { + int indexValue = (controller->*func)(); + asynStatus status = + controller->getDoubleParam(axis->axisNo(), indexValue, readValue); + if (status != asynSuccess) { + return controller->paramLibAccessFailed( + status, indexName, axis->axisNo(), callerFunctionName, lineNumber); + } + return asynSuccess; +} + +template +asynStatus getAxisParamImpl(A *axis, C *controller, const char *indexName, + int (C::*func)(), char *readValue, + const char *callerFunctionName, int lineNumber, + TypeTag) { + + int indexValue = (controller->*func)(); + asynStatus status = controller->getStringParam( + axis->axisNo(), indexValue, controller->msgSize(), readValue); + if (status != asynSuccess) { + return controller->paramLibAccessFailed( + status, indexName, axis->axisNo(), callerFunctionName, lineNumber); + } + return asynSuccess; +} + +template +asynStatus getAxisParamImpl(A *axis, C *controller, const char *indexName, + int (C::*func)(), char (&readValue)[N], + const char *callerFunctionName, int lineNumber, + TypeTag) { + // Decay the array to char* + return getAxisParamImpl(axis, controller, indexName, func, + static_cast(readValue), callerFunctionName, + lineNumber); +} + +template +asynStatus getAxisParamImpl(A *axis, C *controller, const char *indexName, + int (C::*func)(), std::string *readValue, + const char *callerFunctionName, int lineNumber, + TypeTag) { + int indexValue = (controller->*func)(); + + // Convert the pointer to a reference, since getStringParam expects the + // latter. + std::string &rReadValue = *readValue; + + asynStatus status = + controller->getStringParam(axis->axisNo(), indexValue, rReadValue); + if (status != asynSuccess) { + return controller->paramLibAccessFailed( + status, indexName, axis->axisNo(), callerFunctionName, lineNumber); + } + return asynSuccess; +} + /** * @brief Helper function to set an integer / double / string parameter for an * axis in the paramLib @@ -493,6 +673,7 @@ asynStatus setAxisParam(A *axis, C *controller, const char *indexName, * * @tparam T * @param axis + * @param controller * @param indexName * @param func * @param readValue @@ -506,7 +687,10 @@ asynStatus setAxisParam(A *axis, C *controller, const char *indexName, template asynStatus getAxisParam(A *axis, C *controller, const char *indexName, int (C::*func)(), T *readValue, - const char *callerFunctionName, int lineNumber); + const char *callerFunctionName, int lineNumber) { + return getAxisParamImpl(axis, controller, indexName, func, readValue, + callerFunctionName, lineNumber, TypeTag{}); +} /** * @brief Macro to get an paramLib parameter and error checking the return value @@ -522,10 +706,10 @@ asynStatus getAxisParam(A *axis, C *controller, const char *indexName, * expands into the following code: * ``` * { - * int indexValue = axis->pController()->motorStatusProblem_(); - * asynStatus status = axis->pController()->getIntegerParam(axis->axisNo(), + * int indexValue = controller->motorStatusProblem_(); + * asynStatus status = controller->getIntegerParam(axis->axisNo(), * indexValue, readValue); if (status != asynSuccess) { return - * axis->pController()->paramLibAccessFailed( status, "motorStatusProblem_", + * controller->paramLibAccessFailed( status, "motorStatusProblem_", * axis->axisNo(), __PRETTY_FUNCTION__, * __LINE__); * } @@ -548,4 +732,4 @@ asynStatus getAxisParam(A *axis, C *controller, const char *indexName, return getStatus; \ } while (0) -#endif +#endif \ No newline at end of file diff --git a/src/sinqController.h b/src/sinqController.h index 511536f..c12dd55 100644 --- a/src/sinqController.h +++ b/src/sinqController.h @@ -380,9 +380,17 @@ class epicsShareClass sinqController : public asynMotorController { */ int outstandingForcedFastPolls(); - // Maximum error message buffer size. This is an empirical value which must - // be large enough to avoid overflows for all commands to the device / - // responses from it. + /** + * @brief Return the maximum error message buffer size + * + * This is an empirical value which must be large enough to avoid overflows + * for all commands to the device / responses from it. + * + * @return uint32_t + */ + uint32_t msgSize() { return MAXBUF_; } + + // Maximum message size static const uint32_t MAXBUF_ = 200; // =========================================================================