Reflection

1、what is reflection

Assuming we know the name of a class, how can we dynamically generate an object of a class from the class name string?

In Java programming, this is not a problem. However, the language characteristics of C++ determine that it does not support generating objects through the class name string “ClassXX”, that is to say, in C++ we can use ClassXX* object =new ClassXX to generate objects, but not through ClassXX* object= new “ClassXX” to generate the object. This makes it impossible to achieve adaptive expansion when we expand the functions of nodes and modules, that is, if we introduce a new function module, the simulation engine cannot dynamically perceive its existence.

The reflection mechanism is introduced to solve the problem of adaptive expansion of simulation nodes and functional modules, thereby avoiding deep coupling between codes.

2、C++ reflection principle

Reference code src/Framework/Object.h.

3、How extension modules support reflection

All classes that need to support reflection need to inherit from Object. Taking the class implemented in src/Dynamics/ParticleSystem/SummationDensity.h as an example, the process of supporting reflection consists of two steps

  • Derived from Object or a subclass of Object

    template<typename TDataType>
    class SummationDensity : public virtual ParticleApproximation<TDataType>
    
  • interface declaration

    DECLARE_CLASS(SummationDensity)
    //or
    DECLARE_TCLASS(SummationDensity, TDataType)
    

    Among them, SummationDensity corresponds to the name of the class, and TDataType corresponds to the template parameter

  • interface implementation

    IMPLEMENT_TCLASS(SummationDensity)
    //or
    IMPLEMENT_TCLASS(SummationDensity, TDataType)
    

    Among them, the registration of SummationDensity is completed by defining static variables through DECLARE_CLASS/DECLARE_TCLASS.

DECLARE_TCLASS and IMPLEMENT_TCLASS are required to be defined in the same header file. This method is valid for classes whose implementation files are cpp suffixes. However, there are still some problems with the current NVCC compiler. If the implementation file has a .cu suffix, the defined static variable cannot be initialized, and it needs to be done through an additional class.

A feasible solution is to introduce an additional class for each static link library to complete the initialization, which is introduced in initializeParticleSystem.h

class ParticleSystemInitializer : public Object
{
	public:
		ParticleSystemInitializer();
};

const static ParticleSystemInitializer particleSystemInitializer;

At the same time, define and implement the following constructor in initializeParticleSystem.cpp to complete the explicit call to the class defined in the .cu file.

ParticleSystemInitializer::ParticleSystemInitializer()
{
    TypeInfo::New<LinearDamping<DataType3f>>();
    TypeInfo::New<ParticleIntegrator<DataType3f>>();
    TypeInfo::New<ImplicitViscosity<DataType3f>>();
    TypeInfo::New<DensityPBD<DataType3f>>();
    TypeInfo::New<SummationDensity<DataType3f>>();
    TypeInfo::New<VariationalApproximateProjection<DataType3f>>();
}

Finally, add WHOLEARCHIVE to the CMakeLists.txt ({peridyno_Code_path}/examples/Qt_VtkVisualModule/CMakeLists.txt) of the Qt project: