1

I asked a question about boost::asio here but some additional questions came up today. I have some very simple Server Client structure and at one point this async_write command:

ushort _nSetupReceiveBuffer[_nDynamicSize];
boost::asio::async_write(m_oSocket, boost::asio::buffer(&_nSetupReceiveBuffer, _nDynamicSize),
    [this, self](boost::system::error_code _oError, std::size_t)
    {
        std::cout << _nSetupReceiveBuffer.size() << std::endl;
    });

Unfortunately it results in error: ‘_nSetupReceiveBuffer’ is not captured error. So my questions are:

  1. How can I capture nSetupReceiveBuffer or better capture its reference? (Capturing its reference with [this, self, &_nSetupReceiveBuffer] builds but results in Segmentation fault (core dumped) error even before any data is received, since, I assume, it is executed as callback the original variable is already deleted.)

  2. I use ushort because I want to transmit cv::Mat images with CV_16U setting and tried to follow this idea. Do you have other ideas how to transmit cv::Mat files via boost? I can only use lossless containers, but I want to avoid high CPU loads. In my case the bandwith shouldn't be the problem. However that is only half of the truth, I tried to use a serializer which serializes the image to a string, which worked fine but increased the size dramatically :-(

  3. To avoid the problems from 1. I could make _nSetupReceiveBuffer a member variable, but I need to allocate it dynamically at runtime, which I don't know how to do? And a second drawback would be, that the variable type ushort is fixed, but I want to be flexible, e.g. if I have another video stream of CV_8U type, I need to change it to uchar.
  4. My last approach was to reshape() the cv::Mat and use a std::vector<ushort> as member variabel which stores the single values. Is that reasonable or only generating large overhead? Can I define a vector as member variable without a type specified, or should I define one for each type and then just use the appropriate one?

Thank you for your help.

Martin Herrmann
  • 141
  • 1
  • 2
  • 10

1 Answers1

1
  1. How can I capture nSetupReceiveBuffer or better capture its reference? (Capturing its reference with [this, self, &_nSetupReceiveBuffer] builds but results in Segmentation fault (core dumped) error even before any data is received, since, I assume, it is executed as callback the original variable is already deleted.)

Capturing the reference of a variable that will disappear is useless.

Capturing the variable means you can not pass it to the async call.

  1. To avoid the problems from 1. I could make _nSetupReceiveBuffer a member variable, but I need to allocate it dynamically at runtime, which I don't know how to do?

Use std::vector. This should be lesson 1 in C++.

>And a second drawback would be, that the variable type ushort is fixed, but I want to be flexible, e.g. if I have another video stream of CV_8U type, I need to change it to uchar.

This indicates you should probably separate the IO operation from your class. If you make a type to represent the IO operation, you can make the buffer a member of that type.

  1. My last approach was to reshape() the cv::Mat and use a std::vector as member variabel which stores the single values. Is that reasonable or only generating large overhead? Can I define a vector as member variable without a type specified, or should I define one for each type and then just use the appropriate one?

I'd suggest separating the serialization concerns, and use Boost Serialization, like e.g. given here: Serializing OpenCV Mat_<Vec3f>

If you can be sure your matrices are always continuous, you could use the buffer directly:

boost::asio::async_write(m_oSocket, boost::asio::buffer(mat.ptr(), mat.total()),
    [this, self](boost::system::error_code ec, std::size_t tranferred)
    {
        std::cout << tranferred << std::endl;
    });

Of course, you'll have the same lifetime considerations as with the nSetupReceiveBuffer described above. Also, keep in mind that other threads should not touch the data until the IO operation completes.

sehe
  • 374,641
  • 47
  • 450
  • 633
  • Hi thanks for your detailed answer, two questions: 1. What do you mean with I can not pass it to the async call? Probably I don't fully understand the difference between capture variables and arguments. Capturing the reference of a disappearing variable is useless, this is clear to me, but I was not shure how the lifetime of such variables is handled in the case of lambda expressions, thanks for the info. 3. I understand you in the case that you say using vector is not generating large overhead, right? Hence I should use it more often :-) 4. Thank you very much, this answer seems very good. – Martin Herrmann Jan 15 '18 at 07:57
  • Ah and I forgot: What are you meaning with continuous matrices? Row matrices? – Martin Herrmann Jan 15 '18 at 07:59
  • 1. if the variable isn't declared yet, you can't pass it 2. lambdas [capture by value or reference](http://en.cppreference.com/w/cpp/language/lambda#Explanation) if so declared 3. it is not, plus it has the merit of dynamically allocating instead of putting unknown quantities on the stack 4. no comment :) – sehe Jan 15 '18 at 23:47