So basically do i need to include all my code in the code block generated for a given block or can i somehow do a #INCLUDE in order to add another file ?
I want to make a few SMPS and a lot of elements i wont to reuse here and there and i was considering making something that i can mode across projects without direct code copy paste.
Like a library.
Is this possible? if yes how?
Hi, Immortal.
The default QSpice compiler, the Digital Mars Compiler (DMC.exe) supports compiling multiple C or C++ files with *.h header files into a single *.dll file. However, compiling within the QSpice GUI supports compiling only a single *.cpp file.
So, if you want to split code into multiple *.c/*.cpp files and compile within QSpice, you’ll need to use #include in the main file to pull in the *.c/*.cpp code from the other files. (#include simply inserts the code from that file into the current file during compilation.)
Alternatively, you can invoke the DMC compiler manually (command line) to compile each *.c/*.cpp file into *.obj files and automatically invoke the linker to combine them into the *.dll.
You might want to consider other toolsets (MSVC, MinGW) and IDEs (MSVS, VSCode) and see the DMC notes on my QSpice Github respository.
If you have more specific specific questions/code examples, I’ll be happy to provide more specific answers.
–robert
Hi RDunn,
I’ve been following your suggestion to invoke the DMC compiler via a batch file and generate the median product, which includes the linker files for the .dll.
However, I ran into an issue: the generated .dll cannot be compiled, and I get the error [no evaluation function found].
I’ve read through the related issue page and it seems the problem is not only due to a mismatch between the evaluation function name and the .dll name, but may also involve missing components such as the uData structure and other necessary elements.
Could you clarify what the essential components are for an external .dll to compile successfully in Qspice?
Thanks in advance!
@RDunn Here is a rookie question. In this example, in most simple way, ksk_main.cpp only needs #include "ksk_math.cpp" to be compiled by the Qspice DMC compiler.
However, if I add ksk_math.h, I find that I must have #include "ksk_math.cpp" in the header file for the Qspice DMC compiler to work. If I want my code can compiler through Qspice only, is there any reason to create a .h file for it? Furthermore, am I setting these files correctly?
demo_include.qsch (2.5 KB)
ksk_main.cpp (4.4 KB)
ksk_math.cpp (1.2 KB)
ksk_math.h (370 Bytes)
Hi, gao.
I am pretty sure that I don’t quite understand the question or situation. Perhaps you could upload a *.qsch and *.cpp to demonstrate the issue(s)?
I’ll attach a *.qsch and *.cpp to demonstrate just how minimal a DLL can be. It’s useless – you’ll almost certainly want to have per-instance data with an initialization section in the evaluation function.
So, again, perhaps upload and example?
–robert
minimaldll.cpp (1.0 KB)
Minimal.qsch (2.0 KB)
Hi, Kelvin.
For this specific case, there’s no need to have a ksk_math.h file. Simply include the ksk_math.cpp in ksk_main.cpp file and remove the ksk_math.h includes.
ksk_main.cpp:
#include <malloc.h>
#include “ksk_math.cpp”
ksk_math.cpp:
#include <math.h>
And, delete ksk_math.h.
Pretty sure that’s all I did. Let me know if I got it wrong.
–robert
THX for all the help ill try out myself and see how it goes.
Also #include “ksk_math.cpp” in this case i suppose the “ksk_math.cpp” in in the same folder but can it also be at a higher up folder?
I’m pretty sure that #include can use relative and absolute paths since C was created. Should work with DMC.
–robert
@RDunn Yes, simply include the ksk_math.cpp in ksk_main.cpp file and remove the ksk_math.h is good enough. Just out of curiosity, in what situation would I need to consider writing a .h file if I only intend to use the DMC compiler directly from QSpice?
demo_include.qsch (2.5 KB)
ksk_main.cpp (4.4 KB)
ksk_math.cpp (1.1 KB)
Confirmed that relative and absolute path both work as Robert said.
Thanks for your kind suggestion.
I apologize as I may not have explained my question clearly before.
I have now simplified and attached my original code logic, I would like to ask for advice:
How can I make QSPICE properly recognize and use my DLL??
Should I:
- add an additional wrapper layer around my existing code, or
- directly modify the current
entry.cppimplementation?
At this stage, I’m mainly trying to understand the correct integration approach under my current code structure, rather than optimizing functionality.
Also, please kindly bear with this “buggy” simplified code — I’m still in the learning phase ![]()
entry.cpp (1.2 KB)
entry.h (414 Bytes)
@gao
why not start with the auto generated C++ template?
@physicboy
I’m trying to use QSPICE for verification with an existing real control codebase.
So I assumed that, rather than starting from the auto-generated template, the better approach would be to adapt and integrate my original code into a DLL structure that QSPICE can call.
@gao
In such case, I would suggest you to tinker with autogenerated code and develop a wrapper in that to call your existing code.
you may be interested to look at this:
In this example I developed PWM, sampling, interrupt, and control code to emulate how actual MCU deal with the whole thing
Off the top of my head… Assume that you have two modules, A.cpp and B.cpp, that are included in the main DLL. Assume that B needs to call functions in A. If you include B before A, the compiler will complain that the functions aren’t declared/defined. The solution is to include A before B.
However, you might create circular dependencies (A calls stuff in B and B calls stuff in A). Further, the dependencies might flow through additional *.cpp files. In these cases, you’ll need to declare the functions. If you declare them in A.h and B.h, you can simply include the header files before including the *.cpp files. Then you don’t have to worry about the order of *.cpp includes.
Also – not the same as your use case – if you had a structure that is used to, say, write a binary data file to be processed by a separate *.exe, it would be wise to have the DLL and EXE code use the same structure definition. Putting the definition in a header file would ensure that both use the same definition.
One other observation: C/C++ programmers assume that header files declare functions that are intended to be called from other *.cpp code. This serves to clarify the developer’s intent, to document inter-dependencies, and provide a quick reference to the calling and return parameters. Without the header, a developer may need to read through a large implementation (*.cpp) file.
That’s just a few possible reasons.
–robert
Well, the code seems well-suited to use either approach. You’ll want to allow multiple instances of your DLL block in a schematic. That requires moving state information out of global variables and into a per-instance data structure. That data structure would be allocated in the initialization section of the evaluation function.
You’ve broken the code into sensible functions. It should be easy once you understand how to set it up for QSpice. I’ll try to put together a better skeletal example in a bit.
–robert
@gao, please see if the attached helps. If you haven’t already reviewed my C-Block Basics papers, I suggest that you do that. They are here.
Edit #1: Note that I’ve tried to keep your init() and Sim() calls as separate functions. If your existing code is used in other projects and you need to ensure that the logic in the QSpice DLL is identical in those, this should get you started. If that’s not needed, the DLL code could be simplified. Just trying to give you options…
Edit #2: If you’re not familiar with the process of creating template code with QSpice, you might want to see @KSKelvin’s excellent tutorials.
Let me know if you have questions.
–robert
exampledll.cpp (3.8 KB)
Example.qsch (1.8 KB)
Your suggestions are very helpful.
I noticed your comment about the ordering of the uData values. From what I understand so far, both the pin order and attribute order need to be configured carefully in QSPICE. Is that why you’re using inVals here?
For my initial integration step, I believe the priority is to address the single-instance limitation and the mapping issues.
Do you think it would be a good idea to define a complete set of input/output information in an additional header file as what physicboy did in mcu.h?
Looking forward to your thoughts.
I set up the inVals and outVals arrays simply because it appeared that you planned to implement Sim() to expect arrays. If that’s not a requirement, you can do it differently. But, yes, you need to be careful with the order/types of data elements passed in as uData. If you edit the C-Block in the schematic, the order may change and you’ll need to copy the new definitions into the code.
As for using header files, that’s up to you.


