Welcome, Guest

Author Topic: Bind abstract class  (Read 86 times)

diccy

  • Posts: 2
    • View Profile
Bind abstract class
« on: November 06, 2018, 02:26:58 AM »
Hi there !

I have an issue, trying to bind some C++ abstract class.
What I want to archive, is to send requests from JS, and send back results from C++. Requests and results can hold different data structures, as float, string, vector3, ...

In fact, binding is okay, but I'm struggling reading value from JS.

I tried a strategy like this:

JS side (in fact, this is TypeScript)
Code: [Select]

export enum EType
{
Number = 0,
String,
};

export class ValueHolder
{
public value: any;

protected constructor(_value: any)
{
this.value = _value;
}
}

export class Value_Number extends ValueHolder
{
private __Type: string = "Value_Number";

constructor(_value?: number)
{
super(_value === undefined ? 0.0 : _value);
}
}

export class Value_String extends ValueHolder
{
private __Type: string = "Value_String";

constructor(_value?: string)
{
super(_value === undefined ? "" : _value);
}
}

export class ValueWrapper
{
private __Type: string = "ValueWrapper";
public type: EType;
public valueHolder: ValueHolder = null;

constructor(_type: EType, _value?: any)
{
switch (_type)
{
case EType.String: this.valueHolder = new Value_String(<string>_value); break;
default:           this.valueHolder = new Value_Number(<number>_value); break;
}
}
}


C++ side
Code: [Select]

struct IValueHolder
{
virtual void CoherentBindImpl(Coherent::UIGT::Binder* binder) = 0;
virtual void BindProperties(Coherent::UIGT::TypeDescription& type) = 0;
};

void CoherentBind(Coherent::UIGT::Binder* binder, IValueHolder* pValue);

template <typename TValueType>
struct ValueHolder_T
: public IValueHolder
{
TValueType Value;

virtual void CoherentBindImpl(Coherent::UIGT::Binder* binder) override
{
CoherentBind(binder, this);
}

virtual void BindProperties(Coherent::UIGT::TypeDescription& type) override
{
type.Property("value", &ValueHolder_T<TValueType>::Value);
}
};

enum class EValueType
{
Float = 0,
String,
};

struct ValueWrapper
{
EValueType Type = EValueType::Float;
IValueHolder* ValueHolder = nullptr;

void BindProperties(Coherent::UIGT::TypeDescription& type)
{
type.Property("type", &ValueWrapper::Type);
type.Property("valueHolder", &ValueWrapper::ValueHolder);
}
};


void CoherentBind(Coherent::UIGT::Binder* binder, IValueHolder* pValueHolder)
{
pValueHolder->CoherentBindImpl(binder);
}

void CoherentBind(Coherent::UIGT::Binder* binder, ValueHolder_T<float>* pValueHolder)
{
if (auto type = binder->RegisterType("Value_Number", pValueHolder))
{
pValueHolder->BindProperties(type);
}
}

void CoherentBind(Coherent::UIGT::Binder* binder, ValueHolder_T<std::string>* pValueHolder)
{
if (auto type = binder->RegisterType("Value_String", pValueHolder))
{
pValueHolder->BindProperties(type);
}
}

void CoherentBind(Coherent::UIGT::Binder* binder, ValueWrapper* pValueWrapper)
{
if (auto type = binder->RegisterType("ValueWrapper", pValueWrapper))
{
pValueWrapper->BindProperties(type);
}
}


/* Now i start to struggle */

namespace Coherent
{
namespace UIGT
{
void CoherentReadInternal(Binder* binder, ValueWrapper& valueWrapper)
{
/*
First I want to read type here.
*/

/* From type, I can now instanciate a non-abstract class */
switch (valueWrapper.Type)
{
case EValueType::Float:  { valueWrapper.ValueHolder = new ValueHolder_T<float>();       break; }
case EValueType::String: { valueWrapper.ValueHolder = new ValueHolder_T<std::string>(); break; }
}

/*
Now I have a non-abstract instance, I can read value here.
*/
}
}
}


Am I on a good way? If so, what should I use in place of my comments in CoherentReadInternal? I tried several things but all leaded to fails.
If not, do you have any advices?


Thanks !

Tony

  • Administrator
  • *****
  • Posts: 35
    • View Profile
Re: Bind abstract class
« Reply #1 on: November 08, 2018, 09:12:36 AM »
Hey diccy,

In general, you can achieve the reading of the type and value of the bound object using the ReadProperty and Read methods of the binder. More specifically, the ReadProperty is used to get the property of the object and Read to get the values. In addition, when reading the types/values you should begin with binder->OnReadTypeBegin() and end the reading with binder->OnReadTypeEnd(); so that the stack where the information is stored is cleared once you are done with the reading.

To illustrate this:

Code: [Select]
        void CoherentReadInternal(Binder* binder, ValueWrapper& valueWrapper)
        {
            binder->OnReadTypeBegin();
            unsigned rawType;
            if (binder->ReadProperty("type"))
            {
                /* Read the type of the bound "valueWrapper" and store it in the rawType variable*/
                binder->Read(rawType);
            }

            {
                /* Read the actual values that are stored in the object */
                binder->OnReadTypeBegin();
                binder->ReadProperty("valueHolder");
                binder->ReadProperty("value");

                /*Based on the type of the read type create the corresponding class*/
                switch ((EValueType)rawType)
                {
                case EValueType::Float: {
                    /* read float and create a ValueHolder_T<float> class */
                    int i;
                    binder->Read(i);
                    auto result = new ValueHolder_T<float>();
                    result->Value = i;
                    valueWrapper.ValueHolder = result;
                }
                break;
                case EValueType::String: {
                    /*read string and create a ValueHolder_T<string> class*/
                    const char* ptr;
                    size_t i;
                    binder->Read(ptr, i);
                    auto result = new ValueHolder_T<std::string>();
                    result->Value = std::string(ptr, i);
                    valueWrapper.ValueHolder = result;
                }
                break;
                }
                binder->OnReadTypeEnd();

            }
            binder->OnReadTypeEnd();
        }

Hope this helps :)

Tony,
Support Engineer at Coherent Labs

diccy

  • Posts: 2
    • View Profile
Re: Bind abstract class
« Reply #2 on: November 13, 2018, 03:38:09 AM »
Hi !

Thank you very much, I managed to make it work, you helped a lot !

Tags: