After I had published a sample for C++, I realized that OP had tagged the question with C (not C++). Sorry, my fault. Here a sample in C:
#include <Python.h>
#include <assert.h>
#include <stdio.h>
/* sample enum in C */
enum MQ_HANDSHAKE {
MQ_HANDSHAKE_START,
MQ_HANDSHAKE_OK,
MQ_HANDSHAKE_ERROR
};
/* make Python binding for MQ_HANDSHAKE */
static struct PyModuleDef moduleMQ_HANDSHAKE = {
PyModuleDef_HEAD_INIT,
"MQ_HANDSHAKE", /* name of module */
NULL, /* module documentation, may be NULL */
-1, /* size of per-interpreter state of the module,
* or -1 if the module keeps state in global variables.
*/
NULL /* function table (no functions) */
};
static PyObject* initModuleMQ_HANDSHAKE(void)
{
static PyObject *pSelf = NULL;
if (!pSelf) {
pSelf = PyModule_Create(&moduleMQ_HANDSHAKE);
PyModule_AddObject(pSelf, "START", PyLong_FromLong(MQ_HANDSHAKE_START));
PyModule_AddObject(pSelf, "OK", PyLong_FromLong(MQ_HANDSHAKE_OK));
PyModule_AddObject(pSelf, "ERROR", PyLong_FromLong(MQ_HANDSHAKE_ERROR));
}
return pSelf;
}
/* adds module MQ_HANDSHAKE to Python modules table.
*/
void appendModuleMQ_HANDSHAKE(void)
{
assert(!Py_IsInitialized());
PyImport_AppendInittab("MQ_HANDSHAKE", &initModuleMQ_HANDSHAKE);
}
/* test program */
int main()
{
/* initialize Python extension MQ_HANDSHAKE */
appendModuleMQ_HANDSHAKE();
/* initialize Python interpreter */
Py_Initialize();
/* sample Python program */
static const char *const pyProgram
= "print(\"Hello world (from Python).\")\n"
"\n"
"# import Python extension MQ_HANDSHAKE\n"
"import MQ_HANDSHAKE\n"
"\n"
"# test whether it works\n"
"def printHandshake(value):\n"
" if value == MQ_HANDSHAKE.START:\n"
" print(\"MQ_HANDSHAKE_START\")\n"
" elif value == MQ_HANDSHAKE.OK:\n"
" print(\"MQ_HANDSHAKE_OK\")\n"
" elif value == MQ_HANDSHAKE.ERROR:\n"
" print(\"MQ_HANDSHAKE_ERROR\")\n"
" else:\n"
" print(\"Illegal MQ_HANDSHAKE value!\")\n"
"\n"
"printHandshake(MQ_HANDSHAKE.START)\n"
"printHandshake(MQ_HANDSHAKE.OK)\n"
"printHandshake(MQ_HANDSHAKE.ERROR)\n"
"printHandshake(0)\n"
"printHandshake(1)\n"
"printHandshake(2)\n"
"printHandshake(42)\n";
/* run Python interpreter */
const int ret = PyRun_SimpleString(pyProgram);
if (ret) {
fprintf(stderr, "Execution in PyRun_SimpleString() failed!\n");
}
/* done */
return ret;
}
Compiled and tested in VS2013 with Python 3.6:
Hello world (from Python).
MQ_HANDSHAKE_START
MQ_HANDSHAKE_OK
MQ_HANDSHAKE_ERROR
MQ_HANDSHAKE_START
MQ_HANDSHAKE_OK
MQ_HANDSHAKE_ERROR
Illegal MQ_HANDSHAKE value!
This sample establishs a module MQ_HANDSHAKE which
- has to be appended to the Python tables (using PyImport_AppendInittab())
before PyInitialize() has been called
- has to be imported in the Python code (using import MQ_HANDSHAKE).
The original answer with code in C++:
I took a look at our Python wrappers and made a little sample for OPs case:
#include <Python.h>
#include <cassert>
#include <iostream>
// sample enum in C/C++
enum MQ_HANDSHAKE {
MQ_HANDSHAKE_START,
MQ_HANDSHAKE_OK,
MQ_HANDSHAKE_ERROR
};
namespace Py {
namespace MQ {
// make Python binding for MQ_HANDSHAKE
namespace HANDSHAKE {
static struct PyModuleDef module = {
PyModuleDef_HEAD_INIT,
"mq.Handshake", // name of module
nullptr, // module documentation, may be NULL
-1, /* size of per-interpreter state of the module,
* or -1 if the module keeps state in global variables.
*/
nullptr // function table (no functions)
};
static PyObject* init()
{
static PyObject *pSelf = nullptr;
if (!pSelf) {
pSelf = PyModule_Create(&module);
PyModule_AddObject(pSelf, "START", PyLong_FromLong(MQ_HANDSHAKE_START));
PyModule_AddObject(pSelf, "OK", PyLong_FromLong(MQ_HANDSHAKE_OK));
PyModule_AddObject(pSelf, "ERROR", PyLong_FromLong(MQ_HANDSHAKE_ERROR));
}
return pSelf;
}
} // namespace HANDSHAKE
// make module MQ
static struct PyModuleDef module = {
PyModuleDef_HEAD_INIT,
"mq", // name of module
nullptr, // module documentation, may be NULL
-1, /* size of per-interpreter state of the module,
* or -1 if the module keeps state in global variables.
*/
nullptr // function table (no functions)
};
// initializes module mq
static PyObject* init()
{
static PyObject *pSelf = nullptr;
if (!pSelf) {
pSelf = PyModule_Create(&module);
PyModule_AddObject(pSelf, "Handshake", HANDSHAKE::init());
}
return pSelf;
}
// adds module mq to Python modules table.
void append()
{
assert(!Py_IsInitialized());
PyImport_AppendInittab("mq", &init);
}
} // namespace MQ
} // namespace Py
// test program
int main()
{
// initialize Python extension mq
Py::MQ::append();
// initialize Python interpreter
Py_Initialize();
// sample Python program
static const char *const pyProgram
= "print(\"Hello world (from Python).\")\n"
"\n"
"# import Python extension mq\n"
"import mq\n"
"\n"
"# test whether it works\n"
"def printHandshake(value):\n"
" if value == mq.Handshake.START:\n"
" print(\"MQ_HANDSHAKE_START\")\n"
" elif value == mq.Handshake.OK:\n"
" print(\"MQ_HANDSHAKE_OK\")\n"
" elif value == mq.Handshake.ERROR:\n"
" print(\"MQ_HANDSHAKE_ERROR\")\n"
" else:\n"
" print(\"Illegal MQ_HANDSHAKE value!\")\n"
"\n"
"printHandshake(mq.Handshake.START)\n"
"printHandshake(mq.Handshake.OK)\n"
"printHandshake(mq.Handshake.ERROR)\n"
"printHandshake(0)\n"
"printHandshake(1)\n"
"printHandshake(2)\n"
"printHandshake(42)\n";
// run Python interpreter
const int ret = PyRun_SimpleString(pyProgram);
if (ret) {
std::cerr << "Execution in PyRun_SimpleString() failed!\n";
}
// done
return ret;
}
Compiled and tested in VS2013 with Python 3.6:
Hello world (from Python).
MQ_HANDSHAKE_START
MQ_HANDSHAKE_OK
MQ_HANDSHAKE_ERROR
MQ_HANDSHAKE_START
MQ_HANDSHAKE_OK
MQ_HANDSHAKE_ERROR
Illegal MQ_HANDSHAKE value!
I must admit that I resembled this sample by cheating in our production code which we once did patiently while digging through the online resources. For a basic introduction, I recommend 1. Embedding Python in Another Application.
The root module has to be imported in the Python code before it can be used (import mq in the Python sample code). In our productive code, we did it in a separate preceding call of PyRun_SimpleString(), so that our Python application programmers even don't need to care about this.
I splitted the implementation into multiple modules (mq and mq.Handshake). This surely could be done even shorter by establishing a module mqHandshake with the module variables START, OK, and ERROR.
enums, I make a (sub-)module for eachenumand then addintvariables for the resp. enumerators. (Something likeenumseems not to exist in Python.) May be, it would be possible to sub-class one of the built-in Python integer types but the module/variable trick does properly in our case. Hence, I never tried the sub-classing.