How can I share constants between Python and C++?

I have some communication code going on right now where one end is written in C++ for the Arduino and the other end is written in Python on a PC. Both codes are written on the same computer and both are written using Eclipse if it helps.

The question is about sharing constant definitions. I'm talking about things like a baud rate or in my case command strings. Right now I have to have two sets of strings hard coded into two sets of code and make sure they stay the same. If this was all C++ I would just have a shared .h file with a bunch of #define statements that I could reference by the same name in each code. But since one participant here is Python that solution won't fit.

So what are some options for Python and C++ to both have the same strings (and / or other constants) by the same identifier names and have the actual strings stored only in one place?

I would use a configuration file, that's read by both programs. I've used such files with Python before, there's a library for reading/writing them, and I suppose you can find libraries to read the same for C++.

Not exactly what you asked for but save the .h and convert to py on the fly?

https://github.com/evandrix/cPython-2.7.3/blob/master/Tools/scripts/h2py.py

I ended up putting them in a spreadsheet and then using that to automatically generate the C++ and Python files.

In view of the fact that Python is an interpreted language if you put the constants in a .h file for the C++ program then Python could read and parse that file at startup.

Indeed, there is no need for a special file. Python could read any of the C++ source files. But a special file might make life easiest.

...R

It being interpreted or not doesn't really matter - I'm sure C++ and other compiled languages are perfectly capable of parsing data from a Python file.

wvmarle:
It being interpreted or not doesn't really matter - I'm sure C++ and other compiled languages are perfectly capable of parsing data from a Python file.

But not at compile time :slight_smile:

...R

Python regular expressions to extract constants from a C++ header file. (For simple constants this would be my choice.)

Compile the C++ constants into a DLL / SO with an API for querying the constants. From the C++ side the code is trivial (just call the API). From the Python side this should make the code trivial...
https://docs.python.org/3/library/ctypes.html

The meta-question is "why?" Just do the whole thing in one or the other. Or turn your C++ code into a Python module (that is how Python itself is structured).

Python and C++ work well with: JSON, XML, INI, and various other simple text files. Any of those would make a fine choice for constants.

I'm a big fan of Firebird. Put the constants in a relational database with complete transaction control (including snapshot!).

If placed in an external file it'd be much easier to reconfigure the device, no need for recompilation if you want to just change a value.

Cause the Arduino won't run Python and it's much easier to write the Pc side that way even if I have to keep to files of constants.

Ah. I misunderstood this part...

Delta_G:
...one end is written in C++ for the Arduino...

In which case we are discussing the on-wire protocol between an Arduino and a PC.

How many command strings?

A few tens now. Will grow a lot soon. I think the idea of letting the Python program go read the .h file will be easiest. That's what I'll go for I think.

I have a suggestion: Do not use #define / use const.

From the Python perspective, with #define, you will either have to deduce the datatype or go without that information. In addition, if you add a #define that is not a well formed constant there is a good chance your parser will go haywire.

const not only provides name, datatype, and value, it also has a much more strict syntax which should make parsing nearly trivial.

Huh. I just realized that you can add the constants to your running Python as first-class variables. Got to love self-modifying code.

Since when does Python care about data types? They're all strings though, so no big worry.

The language tries to make it so you, the developer, normally do not have to care. But there is a difference between 17 (exact) and 17.0 (estimate). That difference can sometimes be important; even in Python.

You can run code through the C pre-processor to generate python-compatible include files (essentially defining a meta-language for defining your constants.)

#ifdef PYTHON
#define COMMAND(name, string) name=string
#else // C, C++, etc
#define COMMAND(name, string) const char name[] = string;
#endif
COMMAND(dial, "ATDT")
COMMAND(hangup, "ATH")
COMMAND(answer, "ATA")
BillW-MacOSX-2<4993> avr-cpp -P -DPYTHON constants.h 

dial="ATDT"
hangup="ATH"
answer="ATA"

BillW-MacOSX-2<4994> avr-cpp constants.h

1 "constants.h"

1 ""

1 ""

1 "constants.h"

const char dial[] = "ATDT";
const char hangup[] = "ATH";
const char answer[] = "ATA";

Note that cpp won't preserve indentation, so you'll be somewhat limited as to where the pre-processed output can be included in a python program...

Clever. I like it. That can just be an extra step in building the C++ image.

(I wonder what it means that I've used a very similar technique ... uh ... more than a year ago and had completely forgotten about it.)

It does when parsing variables and some are character strings and others are numerical values... You can parse them all as string, but doing maths with strings doesn't really work well, even in Python.

westfw:
You can run code through the C pre-processor to generate python-compatible include files (essentially defining a meta-language for defining your constants.)

What advantage would that have compared to getting the Python code to read a .h file?

What might the output of the pre-processor look like, in comparison to what would be in the .h file?

To quote Reply #10

Cause the Arduino won't run Python and it's much easier to write the Pc side that way

why go to the trouble of using C pre-processor stuff to do something when it is easier to do the same thing in Python?

IMHO C pre-processor stuff is even more opaque than C/C++ :slight_smile:

...R