简体   繁体   中英

PyArg_ParseTupleAndKeywords throws warning: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]

Search for examples on how to use the PyArg_ParseTupleAndKeywords I found these questions:

  1. How can one use PyArg_ParseTupleAndKeywords to parse a tuple with optional arguments as well as keywords?
  2. How does PyArg_ParseTupleAndKeywords work?

They both use things like static char* kwlist[] = {"a", "b", NULL}

static int PyClass_init(PyClass* self, PyObject* args, PyObject* kwargs) {
    char* path;
    char* regex;
    static char* kwlist[] = {"", "", NULL};

    if( !PyArg_ParseTupleAndKeywords( args, kwargs, "s|s", kwlist, &path, &regex ) ) {
        return -1;
    }

    // other code ...
    return 0;
}

Compiling this with language = "c++" on setup.py and build it with -std=c++11 throws this warning:

x86_64-linux-gnu-gcc -pthread -DNDEBUG -g -fwrapv -O0 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -Isource -I/usr/include/python3.6m -c source/test.cpp -o build/temp.linux-x86_64-3.6/source/test.o -O0 -g -ggdb -std=c++11 -fstack-protector-all
source/test.cpp: In function ‘int PyClass_init(PyClass*, PyObject*, PyObject*)’:
source/test.cpp:41:42: warning: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
   static char* kwlist[] = {"a", "b", NULL};
                                          ^

Searching for this error I found this question Why is conversion from string constant to 'char*' valid in C but invalid in C++ taking about a fix, but applying the fix as static char* const kwlist[] = {"a", "b", NULL}; keeps/upgrades the warning introducing the error:

source/test.cpp:41:50: warning: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
     static char* const kwlist[] = {"a", "b", NULL};
                                                  ^
source/test.cpp:41:50: warning: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
source/test.cpp:43:89: error: invalid conversion from ‘char* const*’ to ‘char**’ [-fpermissive]
     if( !PyArg_ParseTupleAndKeywords( args, kwargs, "s|s", kwlist, &path, &regex ) ) {
                                                                                         ^
In file included from /usr/include/python3.6m/Python.h:117:0,
                 from source/test.cpp:3:
/usr/include/python3.6m/modsupport.h:17:41: note:   initializing argument 4 of ‘int _PyArg_ParseTupleAndKeywords_SizeT(PyObject*, PyObject*, const char*, char**, ...)’
 #define PyArg_ParseTupleAndKeywords     _PyArg_ParseTupleAndKeywords_SizeT
                                         ^
/usr/include/python3.6m/modsupport.h:17:41: note: in definition of macro ‘PyArg_ParseTupleAndKeywords’
 #define PyArg_ParseTupleAndKeywords     _PyArg_ParseTupleAndKeywords_SizeT
                                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: command 'x86_64-linux-gnu-gcc' failed with exit status 1

How can I get rid of the warning using an equivalent construct to static char* kwlist[] = {"a", "b", NULL} with C++ 11 while being compatible with Python C API requirements?


Update

After suggested I tried static const char* kwlist[] = {"a", "b", NULL} but PyArg_ParseTupleAndKeywords does not accept it:

source/test.cpp:43:89: error: invalid conversion from ‘const char**’ to ‘char**’ [-fpermissive]
     if( !PyArg_ParseTupleAndKeywords( args, kwargs, "s|s", kwlist, &filepath, &rawregex ) ) {
                                                                                         ^
In file included from /usr/include/python3.6m/Python.h:117:0,
                 from source/test.cpp:3:
/usr/include/python3.6m/modsupport.h:17:41: note:   initializing argument 4 of ‘int _PyArg_ParseTupleAndKeywords_SizeT(PyObject*, PyObject*, const char*, char**, ...)’
 #define PyArg_ParseTupleAndKeywords     _PyArg_ParseTupleAndKeywords_SizeT
                                         ^
/usr/include/python3.6m/modsupport.h:17:41: note: in definition of macro ‘PyArg_ParseTupleAndKeywords’
 #define PyArg_ParseTupleAndKeywords     _PyArg_ParseTupleAndKeywords_SizeT
                                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: command 'x86_64-linux-gnu-gcc' failed with exit status 1

The sample code you copied from is probably C, where the warning isn't as seriously considered ( gcc reports no error on such a code, where g++ pops a warning even with no warning options).

The fix here is to add const keyword like this:

static const char* kwlist[] = {"a", "b", NULL};

The const keyword you tried wasn't applying to the values but to the pointers.

Then to make the function accept a char ** use const_cast :

const_cast<char **>(kwlist)

like this:

PyArg_ParseTupleAndKeywords( args, kwargs, "s|s", const_cast<char **>(kwlist), &path, &regex ) ) 

The function isn't going to change the values by implicit "contract" (because it's python API, it's not going to lie to you), so in this case, casting to const is fine)

PS: The alternative given by this other answer also works. Note that using empty mutable strings is not safer than casting to constant, as if the called function decided to write into empty strings, it would also invoke undefined behaviour.

Use a mutable empty string:

char empty[] = "";
static char* kwlist[] = {empty, empty, NULL};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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