1

I'm trying to use SuperObject in a C++Builder application for JSON marshalling.

SuperObject has some generic functions to help with this:

  TSuperRttiContext = class
  ...
    function AsType<T>(const obj: ISuperObject): T;
    function AsJson<T>(const obj: T; const index: ISuperObject = nil): ISuperObject;
  end;

In the generated .hpp, they appear as this.

class PASCALIMPLEMENTATION TSuperRttiContext : public System::TObject
{
    ...
    template<typename T> T __fastcall AsType(const _di_ISuperObject obj);
    template<typename T> _di_ISuperObject __fastcall AsJson(const T obj, const _di_ISuperObject index = _di_ISuperObject());
};

All fine so far. I can compile code like this

TMyObject * myObject = ...;
_di_ISuperObject obj = superRttiContext->AsJson(myObject);

String s = obj->AsString();

But, I can't link it.

[ILINK32 Error] Error: Unresolved external 'System::DelphiInterface<Superobject::ISuperObject> __fastcall Superobject::TSuperRttiContext::AsJson<TMyObject *>(const TMyObject * const, const System::DelphiInterface<Superobject::ISuperObject>)' referenced from C:\FOO.OBJ

Now, this isn't totally unexpected: The Embarcadero DocWiki says this will happen if the template isn't instantiated within Delphi code.

But, here's the problem - TMyObject is a C++ object descended from TObject, so I can't see how to instantiate the template from Delphi code.

Any ideas?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Roddy
  • 66,617
  • 42
  • 165
  • 277
  • You can use a JSON reader/writer in C++; see http://stackoverflow.com/questions/3512650/fastest-json-reader-writer-for-c – mh taqia Aug 25 '13 at 14:08
  • Can you create a similar object in Delphi to use instead of TMyObject, and then use the generated C++ equivalent from the generated .hpp file? – nachbar Aug 27 '13 at 03:44

1 Answers1

2

You could try:

a) In Delphi, create an adapter for TSuperRttiContext.

type
  TAdapterSuperObject<T : class> = class
    constructor Create();
    destructor Destroy(); override;
    function ObjectToJson(value : T) : String;
    function JsonToObject(value : String) : T;
  end;

function TAdapterSuperObject<T>.JsonToObject(value: String): T;
var
  iso : ISuperObject;
  ctx : TSuperRttiContext;
begin
  ctx := TSuperRttiContext.Create;
  try
    try
    iso := SO(value);
      Result := ctx.AsType<T>(iso)
    except
      on e: Exception do
        raise Exception.Create('JsonToObject error: ' + e.Message);
    end;
  finally
    iso := Nil;
    ctx.Free;
  end;
end;

function TAdapterSuperObject<T>.ObjectToJson(value: T): String;
var  
  ctx : TSuperRttiContext;
begin
  ctx := TSuperRttiContext.Create;
  try
    try
    Result := ctx.AsJson<T>(value).AsString;
    except
      on e: Exception do
        raise Exception.Create('ObjectToJson error: ' + e.Message);
    end;
  finally
    ctx.Free;
  end;
end;

b) using the adapter to declare your classes and use them in c++

type
  TAdapterInfo = class(TAdapterSuperObject<TInfo>);

c) finally, in c++ invoke the adapters:

TAdapterSuperObject__1<TInfo*>* adapterInfo = new TAdapterSuperObject__1<TInfo*>();
...
adapterCliente->ObjectToJson(aInfo);
...

Basically that's the idea i used and worked with Delphi generics within c++.

pochit0
  • 21
  • 2
  • Thanks - that's given me some food for thought! In step B, Does that mean you can instantiate a Delphi template for a C++ class that's just forward declared? – Roddy Sep 20 '13 at 10:53