我想使用 Tcl-C代码在 C 中创建一个名为 MqHandShakeE 的 IntEnum 子类。示例作为模板
int NS(Get_MqHandShakeE_FromObj) (Tcl_Interp *interp, Tcl_Obj *enumE, enum MqHandShakeE *ret) {
int index;
const static struct LookupEnumE keys[] = {
{ "START", MQ_HANDSHAKE_START },
{ "OK", MQ_HANDSHAKE_OK },
{ "ERROR", MQ_HANDSHAKE_ERROR },
{ NULL, 0 }
};
TclErrorCheck (Tcl_GetIndexFromObjStruct (interp, enumE, &keys,
sizeof(struct LookupClassS), "enum", TCL_EXACT, &index));
*ret = keys[index].val;
return TCL_OK;
}
我的目标是使用…来调用python函数。
myfunc … MqHandShakeE.OK …
C常数MQ_HANDSHAKE_START
是 INTEGER
仅Python解决方案:
from enum import IntEnum
class WAIT(IntEnum):
NO = 0
ONCE = 1
FOREVER = 2
这是类型安全的,因为WAIT.NO
具有类型WAIT
和值0
…这可以检查…从下往下的子模块方法是不是类型安全的…WAIT.NO
作为子模块的类型为int
答案 0 :(得分:1)
发布了C ++示例后,我意识到OP用C(不是C ++)标记了这个问题。对不起,我的错。这是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;
}
在VS2013中使用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!
该示例建立了一个模块MQ_HANDSHAKE
,该模块
-必须附加到Python表中(使用PyImport_AppendInittab()
)
在PyInitialize()
被调用之前
-必须以Python代码导入(使用import MQ_HANDSHAKE
)。
使用C ++代码的原始答案:
我看了看我们的Python包装器,并为OP案例做了一些示例:
#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;
}
在VS2013中使用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!
我必须承认,我欺骗了我们的生产代码,使之类似于此示例,我们曾经在浏览在线资源时耐心地这样做。对于基本介绍,我建议使用1. Embedding Python in Another Application。
在使用根模块之前,必须先将其导入Python代码中(Python示例代码中的import mq
)。在我们高效的代码中,我们是在PyRun_SimpleString()
的一个单独的先前调用中完成的,因此我们的Python应用程序程序员甚至不需要关心这一点。
我将实现分为多个模块(mq
和mq.Handshake
)。通过使用模块变量mqHandshake
,START
和OK
建立模块ERROR
,无疑可以做得更短。
答案 1 :(得分:0)
这是我的答案…在python-C-api中创建类型安全 IntEnum 类。