Search code examples
c++delphic++builderbuilderosc

Constructing DynamicArray with NULL in C++ Builder


I want to use the DelphiOSCUtils library in C++Builder.

The problem might be that it uses Generics, and C++Builder cannot handle Generics well.

The code inside the lib is like:

USES ..., System.Generics.Collections; 

TOSCMessage = class(TOSCPacket)
private
  ...
public
  constructor Create(Address: string); overload;
  constructor Create(Bytes: TBytes); overload;

or

  TOSCPacket = class (TObject)
  private
   ...
  public
    constructor Create(Bytes: TBytes);
  end;

The HPP file generated is:

class PASCALIMPLEMENTATION TOSCBundle : public TOSCPacket
{
    typedef TOSCPacket inherited;
private:
   ...
public:
    __fastcall TOSCBundle(System::DynamicArray<System::Byte> Bytes);
    __fastcall virtual ~TOSCBundle(void);
    __classmethod virtual TOSCPacket* __fastcall Unpack(System::DynamicArray<System::Byte> Bytes, int PacketOffset, int Count, System::Extended TimeTag = 0.000000E+00)/* overload */;
    /* Hoisted overloads: */    
public:
};

When I try to create a new TOSCMessage obj in C++

TOSCBundle *bundle = new TOSCBundle(NULL);

I get an error:

E2285 Could not find a match for 'TOSCBundle::TOSCBundle(int)'

Anyone has some pointers on how to fix this?


Solution

  • Your issue has nothing to do with Generics.

    In C++, NULL is (usually) defined as an alias for an integer constant 0. But TOSCBundle does not have a constructor that accepts an int as input. That is what the compiler is complaining about in your case.

    The TOSCBundle constructor you are trying to call takes a System::DynamicArray<System::Byte> object by value, so you have to pass it an actual DynamicArray<Byte> object to copy from. However, unlike in Delphi where you can initialize a dynamic array from nil, in C++ you can't construct a DynamicArray from NULL (or even from nullptr in C++11 and later). DynamicArray does not have a constructor for that.

    So, to pass in an empty array, you will have to pass in a default-constructed DynamicArray object. In this case, a temporary object will suffice, eg:

    TOSCBundle *bundle = new TOSCBundle(DynamicArray<Byte>());
    

    Or, you can use the System::Sysutils::TBytes alias (which is what the Delphi code you showed is using anyway):

    #include <System.SysUtils.hpp>
    
    TOSCBundle *bundle = new TOSCBundle(TBytes());