Python CApi…如何从C创建一个“IntEnum”对象

2024-04-19 00:19:43 发布

您现在位置:Python中文网/ 问答频道 /正文

我想在C中使用Tcl-C-Code创建一个名为MqHandShakeEIntEnum子类作为模板

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;
}

我的目标是用

^{pr2}$

C-常数MQ_HANDSHAKE_START是一个整数

仅Python解决方案:

from enum import IntEnum
class WAIT(IntEnum):
  NO  = 0
  ONCE = 1
  FOREVER = 2

这是类型安全的,因为WAIT.NO具有类型WAIT和值0……这一点我可以检查……从下到下的子模块方法是不是类型安全的WAIT.NOas子模块的类型是int


Tags: 类型indexokenumkeystclstartint
2条回答

我在发布了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;
}

使用Python 3.6在VS2013中编译和测试:

^{pr2}$

此示例建立一个模块MQ_HANDSHAKE,该模块 -必须附加到Python表中(使用PyImport_AppendInittab()) 在调用PyInitialize()之前 -必须在Python代码中导入(使用import MQ_HANDSHAKE)。在


< C++中的原始答案:

我看了一下我们的Python包装器,并为OPs案例做了一个小示例:

#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;
}

使用Python 3.6在VS2013中编译和测试:

^{pr2}$

我必须承认,我很像这个例子,在我们的生产代码作弊,我们曾经耐心地在网上挖掘资源。对于基本介绍,我建议使用1. Embedding Python in Another Application。在

根模块必须在Python代码中导入才能使用(Python示例代码中的import mq)。在我们的高效代码中,我们在前面的一个单独的调用PyRun_SimpleString()中完成了这项工作,因此我们的Python应用程序程序员甚至不需要关心这个问题。在

我将实现分成多个模块(mqmq.Handshake)。通过使用模块变量STARTOK和{}建立一个模块mqHandshake,这当然可以缩短。在

这是我的答案…在python-C-api中创建一个类型安全的类。在

Python C-API… how to write python code in C

相关问题 更多 >