DLL Data structure initialization help

Hi,

I need your help regarding the initialization of a data structure member with non-zero value. This is my data structure:

struct sSTESTE_DLL_X1
{
// declare the structure here
double lastT;
unsigned int cnt;
bool clk_n1;
unsigned long long int cnti;
double pwr;
double pwr_n1;
double iref;

// technically, we need initialize only non-zero data members
sSTESTE_DLL_X1() : lastT(0.0), cnt(0), clk_n1(0), cnti(0), pwr(0.0), pwr_n1(0.0), iref(2.0){};
};

The iref param should have a value higher than zero at simulation start. After the start it will be updated according to a specific rule (incremented or decremented by a fixed term, +/- 0.2). I used an output port to check it but I notice that at start the initialization value is zero. However, the increment/decrement part works correctly.

Thanks in advance

Hi, EMRod.

You are using new (not malloc()) to allocate the instance, right?

If so, maybe post the schematic and code to save us a step reproducing the problem.

–robert

Hi Robert.

Here are the schematic and the code.

Eduardo

steste_1.cpp (2.7 KB)
Test.qsch (3.9 KB)

Hi, Eduardo.

OK, the constructor isn’t called because you’re allocating the struct with malloc(). Constructors are a C++ feature; you need to use new/delete. See attached.

Note: The DMC compiler is a C++ compiler, i.e., you’re really compiling a C++ program, not a C program.

–robert

steste_1.cpp (2.8 KB)

Robert,

It is clear now. I definitely need to learn C++ because I only programme in C.

Thank you.

Eduardo

If you do, I suggest that you learn using a more modern compiler toolset. The DMC compiler is no longer maintained and ended with support for C++98/C99 standards.

DMC compiler notes/links: “About the QSpice Compiler (DMC)”.

–robert

For people like me with limited knowledge in programming, I have to document the method for future reference. By including this constructor initialization, I have learned from you guys that there are three methods to initialize member variables so far.

The essential words are “so far.” :wink:

1 Like

@Kelvin, I’ll give a couple of additional techniques in separate posts…

First, modern C++ compilers (not DMC) support this syntax:

struct sDLLVAR {
  // declare the structure here
  float a     = 1.0;
  float init  = 0.0;
  float lastT = 0.0;
};

Or equivalently:

struct sDLLVAR {
  // declare the structure here
  float a{1.0};
  float init{0.0};
  float lastT{0.0};
};

Again, no help for those using DMC.

–robert

And we could modify a prior example like this:

struct sDLLVAR {
  // declare the structure here
  double a;       // maybe float was ok but looses precision
  double lastT;   // type should match t...

  // sDLLVAR() : a(1.0), lastT(0.0) {};
  sDLLVAR() {
    a     = 1.0;
    lastT = 0.0;
  }
};

Again, this example uses a C++ constructor and must be allocated with “new” as before.

Note that the constructor is a function/method. The prior version had an empty function body. Above, we’ve moved the initialization into the function body. We could, in fact, do much more interesting things in the function body…

–robert

Hello Robert,

Can you suggest a modern compiler toolset?

Eduardo

Continuing with C++, we can also pass a value as a constructor parameter. Let’s say that our component passes in a “gain” value as an attribute named “GainAttr”. We want to store that in our instance data. We could do this:

struct sDLLVAR {
  // declare the structure here
  double a;       // maybe float was ok but looses precision
  double lastT;   // type should match t...
  double gain;    // gain from component attribute

  sDLLVAR(double gainVal) : a(1.0), lastT(0.0), gain(gainVal) {};
  // or
  sDLLVAR(double gainVal) : a(1.0), lastT(0.0), { gain = gainVal; };
};

In the initialization, we’d do this:

*opaque = new sDLLVAR(GainAttr);

We could do more by adding a “destructor” that’s called when “delete inst;” is invoked. That would be useful to (for example) open a file in the constructor and close it in the destructor. But I’ll stop here – I imagine that I’ve muddied the water enough. :wink:

–robert

1 Like

Sure. I use Visual Studio 2022 Community Edition (free from Microsoft) and MinGW (also free). VS includes a (possibly overwhelmingly complete) IDE with debugger and compiler. MinGW is a compiler-only toolset and does not have an IDE. You can use VSCode (a free simplified IDE from Microsoft; IDE only but supports many compiler toolsets for many platforms via plug-ins) with both compilers.

Visual Studio download
MinGW download
VSCode download
VSCode setup info
Sample VSCode Configuration (.vscode)

Visual Studio is probably the easiest to install.

Note: VSCode’s concept of a project is a bit confusing. It’s really simply a folder with configuration in the .vscode subfolder.

–robert

One more suggestion, Kelvin. Given this from your example method 1:

  if (!*opaque) {
    *opaque = (struct sDLLVAR *)malloc(sizeof(struct sDLLVAR));
    bzero(*opaque, sizeof(struct sDLLVAR));

    (*opaque)->a = 1;
  }
  struct sDLLVAR *inst = *opaque;

I always rearrange things slightly so that the “(*opaque)->” syntax is simplified:

  struct sDLLVAR *inst = *opaque;   // moved
  if (!inst) {
    *opaque = inst = (struct sDLLVAR *)malloc(sizeof(struct sDLLVAR));
    bzero(inst, sizeof(struct sDLLVAR));

    // assign initial value (method 1)
    inst->a = 1;
  }

Also works for method 3.

I just find the second version easier if I need to make many “inst->” assignments/initializations.

Maybe I’ll stop now. :roll_eyes:

Thank you Robert.

Eduardo

To ensure iref initializes correctly to 2.0:

  1. Check Instance: Verify you’re monitoring the correct instance of sSTESTE_DLL_X1.
  2. Constructor Use: Make sure you’re always using the constructor for initialization.
  3. Avoid Default Initialization: Ensure there are no uninitialized global or static instances.
  4. Debug Output: Add a debug print in the constructor to confirm it’s being called and iref is set as expected:

cpp

Copy code

std::cout << "Constructor called. iref initialized to: " << iref << std::endl;

If iref still shows as 0, double-check when and how you’re checking its value.

4o mini