EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  <20242025  Index 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  <20242025 
<== Date ==> <== Thread ==>

Subject: Help trying to pass std::vectors as areaDetector attributes
From: Marco Filho via Tech-talk <tech-talk at aps.anl.gov>
To: "tech-talk at aps.anl.gov" <tech-talk at aps.anl.gov>
Cc: George Kontogiorgos <george.kontogiorgos at ess.eu>
Date: Wed, 18 Sep 2024 15:10:49 +0000

Good afternoon all.

Long text ahead summarized: can we add in ADCore the possibility of having std::vector as NDAttributes similarly to what is done with std::string? Does that make sense?

Explanation:

We are trying to use NDAttributes in a detector driver integration and for several reasons we came to the conclusion that this data was best represented by std::vector. (Maybe there is a better way to do that?)
Since there is no NDAttrDataType for std::vector, the way we could initially do this was by passing the address to the vector's pointer to pAttributeList->add() and representing it as a NDAttrUInt64, which feels a bit ugly, but kinda works...

IN DRIVER:
##############################

std::shared_ptr<std::vector<uint32_t>> MyAttrVal = std::make_shared<std::vector<uint32_t>>;
MyAttrVal->push_back(42);
(...)
pArray->pAttributeList->add("Cool Attribute", "Description", NDAttrUInt64, &MyAttrVal); // So we are passing the address to a vector's pointer...
// Driver then doCallbacksGenericPointer, etc.
################################
IN PLUGIN:
################################
//Inside processCallbacks...
NDAttribute * pToAttr = pArray.pAttributeList->find("Cool Attribute");

std::vector<uint32_t> * pAttrVec;
pToAttr->getValue(NDAttrUInt64, &pAttrVec); //Again, addres to pointer...
// Do vector stuff...
################################

However, this only works because the shared pointer is instantiated in a "while (true)" scope, that is: the vector is always the same, being written to by the driver and read from by the plugin at the same time.
If the vector is created inside a scope that actually has an end (anything other than while (true)) then it's certain segmentation fault for us poor foolish mortals.
This is becoming messy...

We tried simply creating vectors, instead of vector pointers:

IN DRIVER:
################################

std::vector<uint32_t> MyAttrVal;
MyAttrVal.push_back(SomeIntValue);
(...)

pArray->pAttributeList->add("Even Cooler Attribute", "Description", NDAttrUInt64, &MyAttrVal); // Passing the address to the actual vector...
// Driver then doCallbacksGenericPointer, etc.
################################
IN PLUGIN
################################
//Inside processCallbacks...
NDAttribute * pToAttr = pArray.pAttributeList->find("Even Cooler Attribute");

std::vector<uint32_t> pAttrVec;
pToAttr->getValue(NDAttrUInt64, &pAttrVec); //Address to actual vector...
// Do vector stuff...

################################

This segfaulted, I assume because pAttributeList->add() calls pAttribute->setValue() which will try to cast a vector to epicsUInt64:

    case NDAttrUInt64:
      this->value_.ui64 = *(epicsUInt64 *)pValue;

And then things blow up because casting back from this to vector doesn't make sense.

Well, we are left with three options, in order of my personal preference:

1- Try to add vector as attributes in ADCore. Would this be a welcome PR in the community? Does it make sense given the framework's way of operation?
2 - Add a second address to the driver, put the vectors data inside an NDArray as a generic pointer and pass it to the plugins. I don't like this, since it creates a customized structure that is not actually what an array is supposed to be. But it solves this problem...
3 - Poke around the casting made by pAttributeList->add() and similars to see if any of those would actually give my vector back. Feels ugly and catastrophic, but might work?

Did anyone else try to do something similar? Is there any other way to do this?

Is a PR that does this welcome in the community?

Thanks for any help and discussions.

Cheers,

Marco



Navigate by Date:
Prev: Re: New to EPICS - wants to use motorMotorSim - Python client Guijarro Mathias Charles via Tech-talk
Next: LabJack EPICS error? Jesse Hopkins via Tech-talk
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  <20242025 
Navigate by Thread:
Prev: EPICS Cyber Security References White, Greg via Tech-talk
Next: LabJack EPICS error? Jesse Hopkins via Tech-talk
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  <20242025 
ANJ, 18 Sep 2024 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions ·
· Download · Search · IRMIS · Talk · Documents · Links · Licensing ·