-2

I am using a 3rd party SDK in my project which accepts void * pointer for setting user specific metadata. But my metadata is in cv::Mat format thus I need to cast the cv::Mat as void * pointer as shown here:

void *set_metadata_ptr(cv::Mat frame)
{

  cv::Mat *user_metadata = new cv::Mat();

  frame.copyTo(*user_metadata);

  return (void *)user_metadata;
}

void foo() 
{
  UserMeta *user_meta = /* ... */;
  user_meta->user_meta_data = (void *)set_metadata_ptr(frame);
}

This works good, but many of the OpenCV power users discourage using pointers with cv::Mat as cv::Mat has smart pointer itself. I wonder is there any better way to cast the cv::Mat as void-pointer in my case?

Top-Master
  • 7,611
  • 5
  • 39
  • 71
neurospark
  • 15
  • 2
  • I think you mean void pointer. – Mohamed Kandeel Oct 03 '21 at 15:04
  • 1
    what you do is awful but if you make sure to eventually delete the newed object, it's tolerable. -- I would recommend creating that Mat without `new` (you know RAII), and passing the address of it. **but** make sure its **lifetime** covers the use of the pointer! -- what is the **real problem** you are trying to solve? give context. https://en.wikipedia.org/wiki/XY_problem – Christoph Rackwitz Oct 03 '21 at 16:03
  • 1
    This is badly asked question. Start from begginig why do you need do that casting (you wrote something about third party library) in details. So what is the library which API you are exactly using what it does and what requirements arguments must meet. There plenty different reasons where `void*` may be needed, from some C like callback to custom version of matrix to some image representation. – Marek R Oct 03 '21 at 17:41
  • My psychic superpowers says this may be related: https://stackoverflow.com/a/17137998/1387438 – Marek R Oct 03 '21 at 17:50

1 Answers1

-2

Simply create your own wrapper:

class MyWrapper {
public:
    cv::Mat frame;
};

Allocate as you normally would:

MyWrapper *ptr = new MyWrapper();
ptr->frame = myOtherFrame;

Then pass where you need, like:

user_meta->user_meta_data = (void *) ptr;

Note that your approach (mentioned in question) is doing a full copy, but above just keeps a reference to an existing smart-pointer.

One liner version:

We could shorten the usage, into:

user_meta->user_meta_data = (void *) new MyWrapper( frame );

If we had a constructor, like:

class MyWrapper {
public:
    explicit MyWrapper(cv::Mat &frame)
        : frame(frame)
    {}

public:
    cv::Mat frame;
};
Top-Master
  • 7,611
  • 5
  • 39
  • 71
  • 3
    that doesn't address the issue (calling `new`, ... avoiding the void cast is probably impossible). it's needless ceremony. instead of doing this, OP can do what they already do. it is (mostly) equivalent but doesn't need the extra class and object. – Christoph Rackwitz Oct 03 '21 at 16:00
  • Remember that `cv::Mat` is a smart-pointer, and we just want a `void *` version; knowing that it's an overkill to do a full copy (using `frame.copyTo(...)`). What OP suggests is copying and quite hardcoded. But a wrapper would work for any smart-pointer type (where `copyTo` would not even exist). – Top-Master Oct 03 '21 at 17:18
  • This is just begging for a leak. Who's the owner? Is ownership being transferred? If so, what if the callback doesn't get called? Why is dynamic allocation needed at all? IMHO OP is suffering from tunnel vision, and you joined them in it. This needs a step back and the architecture changed to something more sensible. – Dan Mašek Oct 03 '21 at 17:27
  • 2
    I doesn't matter OP badly described his problem. It is obvious this i terrible solution in any case. Most probably pointer to accrual data are needed not simple wrapper. – Marek R Oct 03 '21 at 17:38
  • @DanMašek OP is asking for a better solution; his does copy mine not; BTW, let's hope anyone using `new` knows they should call `delete` at some point, or do you suggest we tell OP go and rewrite the third-party-library? (You can comment him such things but this is an answer) – Top-Master Oct 03 '21 at 17:38
  • At least I can give a try to @Top-Master 's suggestion, so that I can learn something new. Although the one liner version returns error like: In constructor ‘constexpr MyWrapper::MyWrapper(cv::Mat&)’: myexample.cpp:179:22: error: call to non-constexpr function ‘cv::Mat::Mat(const cv::Mat&)’ : frame(frame) – neurospark Oct 03 '21 at 18:03
  • @neurospark oops, `constexpr` is meant for things that can be converted to static binary (but smart-pointer is runtime feature). – Top-Master Oct 03 '21 at 18:16
  • @neurospark Use `explicit` instead (which prevents any auto casts, from `cv::Mat` to `MyWrapper`). – Top-Master Oct 03 '21 at 18:19