Generating message type with preprocessor - c++

I want to create a communication protocol between two microcontrollers, I use class logic that incorporates message types between systems. I want to develop a more simple process of creating new messages by doing something very simple like following
BEGIN_MSG(LinearDriveMsg)
ADD_2BIT(DriveSpeed, speed)
ADD_16BIT(GMath::Position, position.x)
END_MSG
Ideally it would expand to:
BEGIN_MSG(LinearDriveMsg)
BEGIN_SERIALIZER
ADD_SERIALIZER_2BIT(DriveSpeed, speed)
ADD_SERIALIZER_16BIT(GMath::Position, position.x)
END_SERIALIZER
BEGIN_DESERIALIZER
ADD_DESERIALIZER_2BIT(DriveSpeed, speed)
ADD_DESERIALIZER_16BIT(GMath::Position, position.x)
END_DESERIALIZER
END_MSG
And then expand to cpp code
...
bool LinearDriveMsg::deserialize(const uint8_t *incoming_buffer, const uint8_t *incoming_size) override{
if (*incoming_size != getMessageSize())
return false;
_speed = (DriveSpeed)((incoming_buffer[0] & SPEED_MASK) >> SPEED_OFFSET);
weldTwoBytesToInt(&incoming_buffer[1], _position.x);
return true;
}
int LinearDriveMsg::serialize(uint8_t *outgoing_buffer, uint8_t *outgoing_size) const override{
if (*outgoing_size < getMessageSize())
return -1;
outgoing_buffer[0] |= ((uint8_t)_speed << SPEED_OFFSET) & SPEED_MASK;
cutIntToTwoBytes(_position.x, outgoing_buffer + 1, 2);
return getMessageSize();
}
...
I know that doing some advanced preprocessor stuff is pretty tricky but maybe there some way to do this task? It is also possible to adjust the actual cpp code to make it possible (in that way that the efficiency is still ok)

I will answer it myself. There is actually "simple" way to solve above task in preprocessor. The boost library offers tools to work approximately in preprocessor like in normal languages. They have a package called preprocessor as part of the boost suite read the docs, you can download it here it is part of the main package.
Main feature that helped to solve the task above was the idea to forward a tuple of arrays to constructs that we know from functional programming. Actually it is BOOST_PP_SEQ_FOR_EACH(macro, data, seq). Another feature that helped to solve the task was this guys implementation to create double parentheses around each element.
As idea it will work like following. I have the above list of tuples:
#define frame_composition (begin_byte(0), begin_bit(0), int8_t, speed)\
(begin_byte(1), begin_bit(4), int16_t, direction)\
I have somekind of sequence of actions, because I want to have serial first and deserial second:
#define COMPOSE_FRAME(seq) \
ADD_SERIAL(seq) \
ADD_DESERIAL(seq)
Now the content of each add category:
#define ADD_SERIAL(seq) \
BOOST_PP_SEQ_FOR_EACH(ADD_SERIAL_ELEM, ~, GLK_PP_SEQ_DOUBLE_PARENS(seq))
#define ADD_DESERIAL(seq) \
BOOST_PP_SEQ_FOR_EACH(ADD_DESERIAL_ELEM, ~, GLK_PP_SEQ_DOUBLE_PARENS(seq)) \
The cool thing is, we have forwarded the same list of tuples to different constructs, to execute some different algorithms. Now the contents of X_ELEM defines:
#define ADD_SERIAL_ELEM(seq) \
outgoing_buffer[BOOST_PP_TUPLE_ELEM( 0, elem)] = (uint8_t) BOOST_PP_TUPLE_ELEM( 3, elem);
#define ADD_DESERIAL_ELEM(seq) \
BOOST_PP_TUPLE_ELEM(3,elem) = (BOOST_PP_TUPLE_ELEM(2,elem)) incoming_buffer[BOOST_PP_TUPLE_ELEM(0,elem)];
And if you need you can distinguish between different use cases in element "functions" with
BOOST_PP_IF(cond, t, f)
To do different things for example on object and simple variables
This is noway complete solution, but to see the idea and that it is possible to create highly portable simple message generator framework out of cpp.

Related

How to get the next enum value from an enum in protobuf?

I have a protobuf message with non-consecutive enum values something like this:
message Information {
enum Versions {
version1 = 0;
version2 = 1;
version3 = 10;
version4 = 20;
version5 = 30;
}
}
I want to have a C++ function GetNextVersion() which takes in one enum version and gives the next version as output. For eg: GetNextVersion(Information::version4) should give Information::version5 as output. Is there any inbuilt and easy method to do this?
You can use protobuf's reflection to achieve the goal:
Information::Versions GetNextVersion(Information::Versions ver) {
const auto *desc = Information::Versions_descriptor();
auto cur_idx = desc->FindValueByNumber(ver)->index();
if (cur_idx >= desc->value_count() - 1) {
throw runtime_error("no next enum");
}
auto next_idx = cur_idx + 1;
return Information::Versions(desc->value(next_idx)->number());
}
int main() {
try {
auto ver = Information::version1;
while (true) {
cout << ver << endl;
ver = GetNextVersion(ver);
}
} catch (const runtime_error &e) {
cout << e.what() << endl;
}
return 0;
}
Is there any inbuilt and easy method to do this?
I see no easy method to get that.
But I can suggest metaprogramming approaches (at least on Linux) with C++ code generation.
You could, assuming you have access to the source code of protobuf-c :
write some GNU gawk script to parse that C++ code and generate the C++ code of GetNextVersion
perhaps write some GNU sed (or a Python one) script doing the same.
write some GCC plugin and use it to parse that C++ code and generate the C++ code of GetNextVersion
write some GNU emacs code doing the same.
wait a few months and (in spring 2021) use Bismon. I am developing it, so contact me by email
extend and adapt the Clang static analyzer for your needs.
extend and adapt the SWIG tool for your needs.
extend and adapt the RPGGEN tool for your needs.
use GNU bison or ANTLR to parse C++ code, or design your domain specific language with some documented EBNF syntax and write some code generator with them.
You could also keep the description of enum Versions in some database (sqlite, PostGreSQL, etc...) or some JSON file or some CSV file (or an XML one, using XSLT or libexpat) and emit it (for protobuf) and the source code of GetNextVersion using some Python script, or GNU m4, or GPP.
You could write a GNU guile script or some rules for CLIPS generating some C++ code with your protobuf description.
In a few months (spring 2021), the RefPerSys system might be helpful. Before that, you could contribute and extend it and reuse it for your needs.
A pragmatic approach could be to add a comment in your protobuf declaration to remind you of editing another file when you need to change the protobuf message and protocol.
No, there isn't.
You define your own data type, so you also must define the operators for it.
So, your GetNextVersion()method contains that knowledge how to increment the version number. If you had decided to use an integer, then the compiler knows already how to increment that, but you wanted something special and that is the price you have to pay for it.

How to convert MQL4 code into C ++ / Delphi DLL (Forex Tester API)?

I need to create an automatic code converterfrom MQL4 API ( a C-like language )into Forex Tester API ( C++ / Delphi DLL ).
There are suggestions that it can be done with the help of ANTLR and MMVP. However, I do not know how it can be done with the help of the above-mentioned technologies.
Could anybody tell how my problem can be solved?
If you do not know how to accomplish my task using ANTLR or MMVP then please advise other technologies.
Here is an example of a simple MQL4 program.
int Count=0; // Global variable.
int init() // Special function init()
{
Print ("init()");
return 0;
}
int start()
{
double Price = Bid;
My_Function();
Print("New tick: ",Count," Price = ",Price);
return 0;
}
int deinit()
{
Print ("deinit()");
return 0;
}
int My_Function()
{
Count++;
return Count;
}
An example of the same program written in C++ API.
#include <windows.h>
#include "StrategyInterfaceUnit.h"
#include "TechnicalFunctions.h"
int Count=0;
char buf[100];
EXPORT void __stdcall InitStrategy()
{
Print ("init ");
}
EXPORT void __stdcall DoneStrategy()
{
Print ("deinit()");
}
EXPORT void __stdcall ResetStrategy()
{
Print ("ResetStrategy()");
}
int My_Function()
{
return Count++;
}
EXPORT void __stdcall GetSingleTick()
{
SetCurrencyAndTimeframe("EURUSD", PERIOD_M1);
double Price = Bid();
My_Function();
sprintf (buf, "New Tick %d Price = %f", Count, Price);
Print(buf);
}
Sample.def
LIBRARY ISHIMOKU
EXPORTS InitStrategy
DoneStrategy
GetSingleTick
ResetStrategy
ReplaceStr
IntrfProcsRec
You were recommended to use ANTLR / MMVP for your Task ?
Well, the core issue is not hidden in the ANTLR kind of tools' capabilities.
I have spent some time researching, if ANTLR could "save" our code-base problems where our IDE ( not the default MetaLang, another, a more flexible, configurable and programmable IDE was used ) still was not able to resolve syntax-errors on brace-matching inside a multi-level commented source code.
While ANTLR is out of question a very powerful horse, one would spend ages to narrow-band specialise into just using this kind of general language-modelling and abstract syntax-tree modelling knowledge.
If your team can spend a few man*years into this learning curve, well, keep planning. If not, there is a high time to review, redesign and reschedule your Project Plan.
Why?
Nota bene: code-conversion is the easiest part...
a need to cover differences in syntax,
a need to cover differences in variables' scope (getting a bit harder)
Lexers may help a bit in this.
Understanding conceptual differences
I like your idea to create a proxy-layer on C++ side, based on target API-services, so as to mediate a missing behaviour on the more flexible part of the MQL4->Forex Tester march route.
In good old days of MQL4, ( when it was indeed an MQL4, not the "New"-hybrid ) I have developed a few syntax-wrappers for similar purposes but with a different motivation, where the plain & simple MQL4 concepts were not feasible to remain help-less.
The proper understanding of both the principal architecture and different modi operandi available in MetaTrader Terminal 4 as a code execution ecosystem of the MQL4 programme types { EA | Script | Indicator } is only a start of the approach once you decided to elaborate a code-conversion from MQL4-DSL-domain into another DSL-domain.
The final nail into the coffin ... syntax creeps in New-MQL4.56789
It is hard not to mention that recent years MQL4 started to become a very different language.
Once can guesstimate what that means for a code-base maintenance, the more what nightmare this represents "behind the curtain" once code-base spans about n-hundreds man years.
Simply put, while the key concepts do not move so often, each new release of either MetaTrader Terminal 4 as a code execution ecosystem or the MetaEditor as a semi-integrated code compilation tool-chain } formerly known as a MetaLang.exe ( pre-New-MQL4.56789... ) ( whereas both are distributed out of ones own control, even with an "enforced update" by a Broker-side operated policy, so no way for a particular "version-freezing" can save you from a mandatory dancing on this mine-field ).
How it can be solved?
If I were in your situation, I would ask the Project Manager / Project Sponsor to state what is the available budget, time constraint and Customer preference for creating such a universal code-convertor.
If feasible, I would launch a new Project with such given Time Schedule / Work-force / Budget and acquire an independent Project Management and Cost Control thereof.
If not feasible, I would ask the Project Steering Committee to redefine metrics and update and publish adapted Project Plan / Work-force / Schedule / Budget for the code-base conversion task to be performed without an automated tool.

Qt #define "signals" clashes with GStreamer (gst)

Qt, which seems to name everything else with an initial Q, does this: #define signals signals in qobjectdefs.h.
However, GStream, not naturally, does not imagine signals to be a reserved word and does this
struct _GDBusInterfaceInfo
{
/*< public >*/
volatile gint ref_count;
gchar *name;
GDBusMethodInfo **methods;
GDBusSignalInfo **signals; <==================
GDBusPropertyInfo **properties;
GDBusAnnotationInfo **annotations;
};
in gdbusintrospection.h.
Am I just to assume that Qt and GStreamer don't play well together., or is there a way around this?
Note: Qt can be persuaded to #define signals signals if I don't #define Q_MOC_RUN. But that leads to problems with classes which are using
class
{
public:
// stuff
signals:
// stuff
private:
// stuff
};
As you might have guessed by now, I am trying to take over code from someone who is not around to support it and Google is not my friend:-(
[Update] Thanks, #IpApp fro the tip (which is not working, alas).
I have been given someone else's code. Apparently it build for target, but has never been built for unit test and I have to do that (why he mix & matched, I do not know).
When I use QT_NO_KEYWORDS in Eclipse CDT, I get errors because the class definition code does not use Q_SINGAL(S) - it uses the signals macro (which is now defined as signals) to define certain public members.
I am not allowed to alter the subsytsem code, just to mock its interfaces, but I am loathe to mock all of Qt & Glib, because of the effort.
Perhaps there is a way to use libraries for one or the other, rather than including their directories into the source path?
Just follow this documentation in your qmake project file:
CONFIG += no_keywords
If you are using something else than qmake, make sure that you define the following in your buildsystem:
QT_NO_KEYWORDS
Then, you need to make sure that you use Q_SIGNALS or Q_SIGNAL all over the place in your headers so that moc (meta object compiler) is still notified that it is a signal.
I have found another solution which as for me is more convenient and simple - you should include glib headers before Qt headers, and thats all. As glib code goes before, it is unaffected by Qt define statements.

Sphinx: Correct way to document an enum?

Looking through the C and C++ domains of Sphinx, it doesn't appear to have native support for documenting enums (and much less anonymous enums). As of now, I use cpp:type:: for the enum type, and then a list of all possible values and their description, but that doesn't seem like an ideal way to deal with it, especially since it makes referencing certain values a pain (either I reference just the type, or add an extra marker in front of the value).
Is there a better way to do this? And how would I go about handling anonymous enums?
A project on Github, spdylay, seems to have an approach. One of the header files at
https://github.com/tatsuhiro-t/spdylay/blob/master/lib/includes/spdylay/spdylay.h
has code like this:
/**
* #enum
* Error codes used in the Spdylay library.
*/
typedef enum {
/**
* Invalid argument passed.
*/
SPDYLAY_ERR_INVALID_ARGUMENT = -501,
/**
* Zlib error.
*/
SPDYLAY_ERR_ZLIB = -502,
} spdylay_error;
There some description of how they're doing it at https://github.com/tatsuhiro-t/spdylay/tree/master/doc, which includes using a API generator called mkapiref.py, available at
https://github.com/tatsuhiro-t/spdylay/blob/master/doc/mkapiref.py
The RST it generates for this example is
.. type:: spdylay_error
Error codes used in the Spdylay library.
.. macro:: SPDYLAY_ERR_INVALID_ARGUMENT
(``-501``)
Invalid argument passed.
.. macro:: SPDYLAY_ERR_ZLIB
(``-502``)
Zlib error.
You could take a look and see if it's useful for you.
Sphinx now has support for enums
Here is an example with enum values:
.. enum-class:: partition_affinity_domain
.. enumerator:: \
not_applicable
numa
L4_cache
L3_cache
L2_cache
L1_cache
next_partitionab
Hi Maybe you should consider using doxygen for documentation as it has a lot more native support for c / c++. if you want to retain the sphinx output of your documentation you can output from doxygen as xml, then using Breathe it will take the xml and give you the same sphinx output you are used to having.
Here is an example of documenting an enum in doxygen format from the breathe website.
//! Our toolset
/*! The various tools we can opt to use to crack this particular nut */
enum Tool
{
kHammer = 0, //!< What? It does the job
kNutCrackers, //!< Boring
kNinjaThrowingStars //!< Stealthy
};
hope this helps.

C++ code generation for repeated task

I have something like below which will get repeated many times based on the function
that get called
for e.g
acceptfunction()
{
inserter["quantity"] = sdd.getfloat(quantity);
inserter["prodtype"] = sdd.getstring(prodtype);
:
:
so on
}
Like accept above there are 20 more functions(reject,cancel etc) which will do the
similar thing.But the parameteres they insert can differ based on function called.
How can I automate this kind of code.So that I dont need to write new function from
scratch.Basically what I need is if i provide parametres like ("quantity",prodtype)
through some text file or xml, it should generate the required function with the
input parametres.
Is this task can be handled through C++ tempalte Meta programming or someother code
generation tool will help me to do this?
It's ugly, but you can use a preprocessor macro:
#define FUNCTION_MACRO(NAME, ATTRIB1, ATTRIB2)\
void NAME()\
{\
inserter[#ATTRIB1] = sdd.getfloat(ATTRIB1);\
inserter[#ATTRIB2] = sdd.getstring(ATTRIB2);\
}
And then to create a function you just need to do:
FUNCTION_MACRO(accept_function, quantity, prodtype)
Well, when it comes down do it, you almost certainly could but it would require implementing an XML or text parser in TMP. Would be quite a feat.
That's not how things would normally be done, but you've not specified enough details to go into it further.
Macros are generally to be avoided, but this is a case where they are still useful. Something like
#define GET_FUNCTION(type, name) \
do \
{ \
inserter[#name] = sdd.get ## type(name); \
} \
while (0)
will let you say
void acceptfunction()
{
GET_FUNCTION(float, quantity);
GET_FUNCTION(string, prodtype);
// etc...
}
(The reason for the odd do-while construct is to guarantee that the result is a single statement.)
Define different macros for rejectfunction(), etc.