Login Page - Create Account

Support Board


Date/Time: Mon, 29 Apr 2024 14:39:04 +0000



Post From: Using Visual Studio C++ to create Custom Studies

[2021-12-20 09:32:31]
User310645 - Posts: 49
In gerneral terms all this is doing is wrapping the lifecyle of calling a study into a C++ wrapper. The main entry point into the study is a normal SCSFExport function. I've attached the SCEntry.cpp below. (I didn't include this as I was replying to the discussion specifically around creating UI components and didn't want to add extra complexity.)

This calls into a static Study base class that is responsible for creating the required component, lifecycle management (eg. SetDefaults etc), initialisation, running the calculation part of the study (DoStudy() ), storing/retrieving the pointer to the component (you need to persist the UI component somewhere between calls) and cleaning up on sc.LastcalltoFunction.

For example:


void Study::Run() {

  if (!Initialised) {
    Init();
  }

  if (_sc->SetDefaults) {
    DoSetDefaults();
    return;
  }

  if (_sc->LastCallToFunction) {
    CleanUp();
    return;
  }

  DoStudy();
}


Study* Study::StartStudy(StudyType StudyType_, SCStudyInterfaceRef sc_) {

  const bool IsDLLInit = sc_.SetDefaults && sc_.ArraySize == 0;

  Study* study = IsDLLInit ? NULL : static_cast<Study*>(sc_.GetPersistentPointer(1));

  if (study == NULL) {
    switch (StudyType_) {
    case STUDY_COMBO:
      study = new ComboStudy(sc_);
      break;
    case STUDY_SLIDER:
      study = new SliderStudy(sc_);
      break;
    case STUDY_THEME:
      study = new ThemeStudy(sc_);
      break;
    case STUDY_POWERMETER:
      study = new PowerMeterStudy(sc_);
      break;
    }
    sc_.SetPersistentPointer(1, study);
  }

  study->SetReferences(&sc_);

  study->Run();

  if (sc_.LastCallToFunction || IsDLLInit) {
    delete study;
    study = NULL;
    sc_.SetPersistentPointer(1, study);
  }
  return study;
}


All the files are compiled together into a single DLL (using Visual Studio) and placed in the data folder just like any other study would be. You could also create libraries of course and link them as required.

Your specific points;

For 2. The initial SCStudyInterfaceRef is passed in the constructor for initialisation. Unfortunately you cannot just store this for the duration of the study as you get a new reference each time Sierra calls into it. Therefore the SetReferences() call is made to update the reference on each call and set any variables that may have changed.

You can perform any operation to subgraphs in exactly the same way. You would just do it in the DoStudy() part.

All the data from the arrays are always in the SCStudyInterfaceRef object. You are accessing them via a reference (or a pointer). If you choose to copy anything then of course it your responsibility to clean it up.

You could write a book on C++ memory management but in general terms anything you create on the heap ie. with "new" (but read about smart pointers) you will have to clean up yourself. Objects used in a function that are created on the stack are cleaned up when the function exits.
Date Time Of Last Edit: 2021-12-20 09:36:25
attachmentSCEntry.cpp - Attached On 2021-12-20 09:09:04 UTC - Size: 977 B - 260 views