简体   繁体   English

Python 3的C / C ++扩展中的关键字解析

[英]Keyword parsing in C/C++ extension for Python 3

I am currently trying to implement a Python module using C++. 我目前正在尝试使用C ++实现Python模块。 Official Python 3 docs provide an example here , but to my surprise the code provided there throws errors in my Visual Studio 2017! 官方Python 3文档在此处提供了一个示例,但令我惊讶的是,其中提供的代码在我的Visual Studio 2017中引发了错误!

If you take a look at Custom_init function implementation, you will see a function call PyArg_ParseTupleAndKeywords that takes several arguments, including a keyword array kwlist declared 3 lines above (Example copy-pasted below): 如果您看一下Custom_init函数的实现,您将看到一个函数调用PyArg_ParseTupleAndKeywords ,它PyArg_ParseTupleAndKeywords多个参数,包括上面3行声明的关键字数组kwlist (下面的示例复制粘贴):

static int
Custom_init(CustomObject *self, PyObject *args, PyObject *kwds)
{
    static char *kwlist[] = {"first", "last", "number", NULL};
    PyObject *first = NULL, *last = NULL, *tmp;

    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|UUi", kwlist,
                                     &first, &last,
                                     &self->number))
        return -1;

    if (first) {
        tmp = self->first;
        Py_INCREF(first);
        self->first = first;
        Py_DECREF(tmp);
    }
    if (last) {
        tmp = self->last;
        Py_INCREF(last);
        self->last = last;
        Py_DECREF(tmp);
    }
    return 0;
}

However upon trying to declare a kwlist of my own like in example above, VS2017 throws the following error: 但是在尝试像上面的示例一样声明自己的kwlist时,VS2017引发以下错误:

a value of type "const char *" cannot be used to initialize an entity of type "char *" 类型“ const char *”的值不能用于初始化“ char *”类型的实体

The simple thing would be to declare my own kwlist as const , but PyArg_ParseTupleAndKeywords expects kwlist as char * . 简单的事情是将我自己的kwlist声明为const ,但是PyArg_ParseTupleAndKeywords期望kwlistchar * (Documentation here ) 此处的文档)

Is there a way to deal with this without resorting to extremes like const_cast ? 有没有一种方法可以解决此问题而无需求助于const_cast极端方法?

Thank you. 谢谢。

EDIT: 编辑:

One of the comments below suggested to simply copy from const char* to char* and I believe that will be the simplest approach to resolve this. 以下评论之一建议将其简单地从const char*复制到char* ,我相信这将是解决此问题的最简单方法。

I cannot think of anything less horrible than 我想不出比这更可怕的了

static char first[] = "first";
static char last[] = "last";
static char number[] = "number";
static char *kwlist[] = {first, last, number, NULL};

You can store the strings as std::string s, and then use std::string::data to get your char * s 您可以将字符串存储为std::string ,然后使用std::string::data来获取char * s

static int
Custom_init(CustomObject *self, PyObject *args, PyObject *kwds)
{
    static std::array<std::string, 4> keywords { "first", "last", "number", "" };
    std::array<char *, 4> kwlist;
    std::transform(keywords.begin(), keywords.end(), kwlist.begin(), [](auto & str){ return str.data(); });

    PyObject *first = nullptr;
    PyObject *last = nullptr;

    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|UUi", kwlist.data(),
                                     &first, &last,
                                     &self->number))
        return -1;

    if (first) {
        auto tmp = self->first;
        Py_INCREF(first);
        self->first = first;
        Py_DECREF(tmp);
    }
    if (last) {
        auto tmp = self->last;
        Py_INCREF(last);
        self->last = last;
        Py_DECREF(tmp);
    }
    return 0;
}

Alternatively, you can use offsets into a single string literal 或者,您可以在单个字符串文字中使用偏移量

static char keywords[] = "first\0last\0number\0\0";
static char * kwlist = { keywords, keywords + 6, keywords + 11, keywords + 18  };

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM