Yes this is for embedded systems programming, where it's historically unusual to use C++. But "embedded systems" covers a broad range of applications. Some segments have embraced C++ for many years. Others still prohibit it. My primary goal is to use templates, rather than maintain a set of handcrafted modules for each data type. Depending on how things work out, it might be possible to use C++ more extensively.
I'm happy to see any interest in my issues and I thank you for your responses. I hope the novelty of this endeavor keeps you interested.
After reading the prior response from Helios, I realized that I needed to broaden the description of my concept. I (foolishly) entered it as a new topic with with
(Part 2) appended to the same topic title.
Fortunately, a response from
TheIdeasMan straightened me out. So I'll try to move forward from here. But it might help if you find and read the
(Part 2) posting. It shows some example code that I got to run and poses some questions.
As I expected, my world differs vastly from the world of the typical C++ forum member. Let me see if I can translate. I'll start with the quadratic equation example from Helios. If this were expressed as a function:
1 2 3 4
|
int QuadFunc(int a, int b, int c)
{
return (-b +- sqrt(b^2 - 4*a*c)) / (2*a)
}
|
This function is wrapped by code that adapts it to my "Data Manager" concept.
Assume that a code generator has statically allocated some resources, such as:
1 2 3 4 5 6 7 8 9 10 11 12
|
DataTyp<int> ArrayInt[4]; // Allocation of int data.
DataTyp<List> ArrayList[4]; // Allocation of List data.
List Root; // Effectively a reference to ArrayList[0].
List QuadInterface; // Effectively a reference to ArrayList[1].
List Inputs; // ref to ArrayList[2]. Referenced by QuadInterface[0].
List Outputs; // ref to ArrayList[3]. Referenced by QuadInterface[1].
ItemRef a; // ref to ArrayInt[0]. Referenced by Inputs[0].
ItemRef b; // ref to ArrayInt[1]. Referenced by Inputs[1].
ItemRef c; // ref to ArrayInt[2]. Referenced by Inputs[2].
ItemRef result; // ref to ArrayInt[3]. Referenced by Outputs[0].
|
The code generator also creates a wrapper function, such as:
1 2 3 4
|
void QuadWrap(ItemRef r) // called with r = QuadInterface.
{
r.Inputs.result = QuadFunc(r.Inputs.a, r.Inputs.b, r.Inputs.c);
}
|
Clearly, the above example is just pseudo code.
The the term "reference" is used loosely here. Not necessarily the specific C++ meaning.
My comment about allocation by the interface was misleading.
The actual allocated values in the above example are all in the two "DataTyp" arrays.
These arrays are allocated by a code generator that accounts for all interfaces in an application.
This was clearly not obvious in my prior post. (Sorry about that.)
At the time, I was considering whether data might be allocated locally in the wrapper interface code.
After composing the above example, it seems like that might not be necessary.
To do that, I'd need a DataTyp<int*> array to reference a pointer to an int allocated outside the DataTyp<int> array.
There are likely many cases I've not yet considered. So I'm keeping an open mind.
It might be useful if static data, allocated within the wrapped function, can be accessed through the Data Manager hierarchy. If so, it would be necessary for the wrapper to copy them to a list of output values.
That means a duplication of storage and a waste of memory.
In outline form, the interface to the QuadWrap example function is:
Root
QuadInterface
Inputs
a
b
c
Outputs
result |
The
Root] list is actually part of the application, which includes QuadInterface as an item.
There would also be a Process Manager with a hierarchical list of function pointers.
DataTyp<List> ArrayFunc[1]; // Allocation of a List of function pointers.
In this example, ArrayFunc[0] points to [b]void QuadWrap(ItemRef r).
This concept also requires two Windows applications that are much more conventional.
- Application Builder
Selects functions from libraries, interconnects interfaces and sets execution sequence.
Generates the code for the embedded controller.
- Service Tool
Connects to a running embedded application.
Allows user to browse the hierarchical data for observation, logging and editing.
These applications can use conventional C++ with few limitations.
But... the more code they share the better.
I expect that code for iterating the hierarchy values can be common to the PC and embedded applications.
It's possible to use a "path" to any item in the hierarchy, from the root list.
For example:
Root\QuadInterface\Outputs\result.
Equivalently, this is a sequence of List subscripts: ArrayList[0] \ ArrayList[1] \ ArrayList[3] \ ArrayInt[3].
A path composed of text labels is used to initially access a list or list element.
Access is managed by the List class, which controls access to its elements.
Once access to any path endpoint is established, further access is direct, using <typ>[num].
This provides a direct reference to the data allocated in the array of a specified type.
In the embedded application, the path is simply a sequence of numbers: {0,1,3,3}.
As I mentioned in my (Part 2) topic, I originally planned to reference an allocated value by {typeNumber, instanceNumber }. (The
ItemRef type in the above example.) But I found no way (short of a switch block) to select an array using typeNumber.
I think now that I might get by with a typed value that contains only instanceNumber. The type would associate it with the correct array of allocated values through template generated function overloading.
This should be more than enough to generate some new questions.
I don't expect anyone to "do my homework".
But questions, suggestions and sanity checks are greatly appreciated.
Just describing this to others (who can understand it) is an excellent exercise for me.