-1

I am using C++ Builder 10.2.3 (Rad Studio 10.2.3) I am trying to convert a TRectF to a Variant. But it seems not to be working:

  • 1st Solution: using TValue::From(rect).AsVariant() or AsType(). I am getting the error message: Invalid Class TypeCast
  • 2e Solution: Using TValue::Make() with ExtractRawData. But I cannot use it because __delphirtti() cannot work with TRectF.

This is an example of code from Qt I am trying to adapt:

void File::appendRects(const QList<QRectF> &rects)
{
    QList<QVariant> newRects = m_metadata["Rects"].toList();
    foreach (const QRectF &rect, rects)
        newRects.append(rect);
    m_metadata["Rects"] = newRects;
} 

The code line newRects.append(rect); adds a QRectF to a QVariant list. Which means that the conversion is done automatically.

Any solution which works?

Louis
  • 75
  • 6
  • _"But I cannot use it because __delphirtti() cannot work with TRectF"_ What's the exact problem. Post a [mcve] if you want to get helped. As is your question is too vague. – πάντα ῥεῖ Aug 06 '21 at 21:25

1 Answers1

1

TRectF is not a type that Variant supports natively, which is why your "solutions" do not work.

To store a TRectF in a Variant, you would have to either:

  • store the TRectF data as a dynamic byte array, eg:
TRectF rect = ...;
int bounds[] = {0, sizeof(rect)-1}; 
Variant v = VarArrayCreate(EXISTINGARRAY(bounds), varByte);
// alternatively:
// Variant v = VarArrayCreate(OPENARRAY(int, (0, sizeof(rect)-1)), varByte);
void *p = VarArrayLock(v);
memcpy(p, &rect, sizeof(rect));
VarArrayUnlock(v);
  • implement TCustomVariantType to represent the TRectF data inside a Variant, per Defining Custom Variants:

    By default, variants cannot hold values that are records, sets, static arrays, files, classes, class references, or pointers. You can, however, extend the Variant type to work with any particular example of these types. All you need to do is create a descendant of the TCustomVariantType class that indicates how the Variant type performs standard operations.

    But, be aware of this caveat:

    Note: C++ can use Custom Variant types, but TCustomVariantType descendants must be implemented in Delphi.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • A list of the types `Variant` supports natively: [TVarData](http://docwiki.embarcadero.com/Libraries/Sydney/en/System.TVarData) – Ted Lyngmo Aug 06 '21 at 21:28
  • The problem is that in Fact TRectF is an example of a bunch of types and user defined classes I will need to convert the same way. I will have to apply the same solution to TRect, TPoint, TPointF, TVariantList, cv::RotatedRect (from OpenCV), etc... Is there a more direct solution? – Louis Aug 06 '21 at 21:51
  • @Louis `Variant` simply doesn't support ANY of those types natively, so you will have to stick with what I said. Why are you trying to put these types into a `Variant` to being with? What are you trying to do with it? – Remy Lebeau Aug 06 '21 at 21:55
  • I have some algorithms written using Qt I am trying to adapt and import in C++ Builder. It happens that those types of conversion are very easy and sometimes just automatic with Qt. – Louis Aug 06 '21 at 21:58
  • @Louis Qt is a pure C+ library, it has no concept of `Variant`, so it is not really clear what you are trying to accomplish exactly. Can you please update your question to provide an example? Perhaps you are trying to adapt logic from Qt's `QVariant` to C++Builder's `Variant`? You will likely end up having to go the `TCustomVariantType` route for that, except for `cv::RotatedRect` which would require even more work to get it into Delphi. `std::variant` may be a better choice, but note that it is severely broken in C++Builder. – Remy Lebeau Aug 06 '21 at 22:01
  • @Louis Changing `QList` to `std::vector` could work if you implemented `TCustomVariantType`, but I probably wouldn't go that route at all. Do consider using `std::variant` instead, if you can live with/workaround [its bugs](https://quality.embarcadero.com/issues/?jql=text%20~%20%22std%3A%3Avariant%22) in C++Builder. – Remy Lebeau Aug 06 '21 at 22:23
  • This is an example of code from Qt I am trying to adapt: ~~~ void File::appendRects(const QList &rects) { QList newRects = m_metadata["Rects"].toList(); foreach (const QRectF &rect, rects) newRects.append(rect); m_metadata["Rects"] = newRects; } ~~~ The code line newRects.append(rect); adds a QRectF to a QVariant list. Which means that the conversion is done automatically. __Sorry I tried to format the code part so that it will appear by lines but does not work --- – Louis Aug 06 '21 at 22:24
  • @RemyLebeau: The link you provided for std::variant bugs opens a blank page https://quality.embarcadero.com/issues/?jql=text%20~%20%22std%3A%3Avariant%22 – Louis Aug 06 '21 at 22:32
  • @Louis works fine for me, but I'm logged in to the system. Did you see the "Try logging in to see more results" comment on that result page? The [opening page](https://quality.embarcadero.com) tells you how to login. – Remy Lebeau Aug 06 '21 at 22:35
  • OK. Good. I can see it when I log in. – Louis Aug 06 '21 at 22:44