从python字符串中提取的C字符数组

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从python字符串中提取的C字符数组相关的知识,希望对你有一定的参考价值。

我在 python 中有一个字符串列表,我想把它传给 C 语言扩展进行字符分析。我已经把这个列表分解成了一个个单独的字符串PyObjects。下一步,我希望将这些字符串分割成各自的字符,这样每一个字符串PyObject现在都是一个对应的C型字符数组。但我似乎不知道如何做到这一点。

这是我目前的情况。目前在构建.pyd文件后,它会返回一个1的列表作为Python的填充物(所以其他一切都能正常工作),我只是不知道如何将一个字符串PyObject分割成C型字符数组。

--- cExt.c ---

#include <Python.h>
#include <stdio.h>

static int *CitemCheck(PyObject *commandString, int commandStringLength) 

    // HAALP

    //char* commandChars = (char*) malloc(commandStringLength*sizeof(char*));

    // char c[] = PyString_AsString("c", commandString);
    // printf("%c" , c);
    // printf("%s", PyString_AsString(commandString));
    // for (int i=0; i<sizeof(commandChars)/sizeof(*commandChars); i++) 
    //     printf("%s", PyString_AsString(commandString));
    //     printf("%c", commandChars[i]);
    // 
    return 1; // TODO: RETURN PROPER RESULTANT


static PyObject *ClistCheck(PyObject *commandList, int commandListLength) 

    PyObject *results = PyList_New(commandListLength);

    for (int index = 0; index < commandListLength; index++) 
        PyObject *commandString;
        commandString = PyList_GetItem(commandList, index);
        int commandStringLength = PyObject_Length(commandString);

        // CitemCheck should take string PyObject and its length as int
        int x = CitemCheck(commandString, commandStringLength);

        PyObject* pyItem = Py_BuildValue("i", x);
        PyList_SetItem(results, index, pyItem);
    
    return results;


static PyObject *parseListCheck(PyObject *self, PyObject *args) 
    PyObject *commandList;
    int commandListLength;

    if (!PyArg_ParseTuple(args, "O", &commandList))
        return NULL;
    

    commandListLength = PyObject_Length(commandList);

    return Py_BuildValue("O", ClistCheck(commandList, commandListLength));


static char listCheckDocs[] = 
    ""; // TODO: ADD DOCSTRING

static PyMethodDef listCheck[] = 
 "listCheck", (PyCFunction) parseListCheck, METH_VARARGS, listCheckDocs,
 NULL,NULL,0,NULL
;

static struct PyModuleDef DCE = 
    PyModuleDef_HEAD_INIT,
    "listCheck",
    NULL,
    -1,
    listCheck
;

PyMODINIT_FUNC PyInit_cExt(void)
    return PyModule_Create(&DCE);


供参考,我的临时扩展构建文件。

--- _c_setup.py --- 
(located in same folder as cExt.c)
"""
to build C files, pass:

python _c_setup.py build_ext --inplace clean --all

in command prompt which is cd'd to the file's dierctory
"""
import glob
from setuptools import setup, Extension, find_packages
from os import path

here = path.abspath(path.dirname(__file__))
files = [path.split(x)[1] for x in glob.glob(path.join(here, '**.c'))]

extensions = [Extension(
    path.splitext(x)[0], [x]
) for x in files]

setup(
    ext_modules = extensions,
)
答案

你可以使用PyUnicode_AsEncodedString,它的作用是

编码和错误与Unicode encode()方法中的同名参数意义相同。使用的编解码器是通过Python编解码器注册表来查找的。如果编解码器引发了异常,则返回NULL。

参见 https:/docs.python.org3c-apiunicode.html#c.PyUnicode_AsEncodedString。

然后用PyBytes_AsString得到一个指向内部缓冲区的指针,末端是一个NUL字节。这个缓冲区既不能被重新定位也不能被修改。如果你需要一个副本,你可以使用例如strdup。

参见 https:/docs.python.org3c-apibytes.html#c.PyBytes_AsString。

稍微修改一下你的代码,可以是这样的。

PyObject *encodedString = PyUnicode_AsEncodedString(commandString, "UTF-8", "strict");
if (encodedString)  //returns NULL if an exception was raised
    char *commandChars = PyBytes_AsString(encodedString); //pointer refers to the internal buffer of encodedString
    if(commandChars) 
        printf("the string '%s' consists of the following chars:\n", commandChars);
        for (int i = 0; commandChars[i] != '\0'; i++) 
            printf("%c ", commandChars[i]);
        
        printf("\n");
    
    Py_DECREF(encodedString);

如果用..:

import cExt

fruits = ["apple", "pears", "cherry", "pear", "blueberry", "strawberry"]         
res = cExt.listCheck(fruits)
print(res)

输出将是:

the string 'apple' consists of the following chars:
a p p l e 
the string 'pears' consists of the following chars:
p e a r s 
the string 'cherry' consists of the following chars:
c h e r r y 
the string 'pear' consists of the following chars:
p e a r 
the string 'blueberry' consists of the following chars:
b l u e b e r r y 
the string 'strawberry' consists of the following chars:
s t r a w b e r r y 
[1, 1, 1, 1, 1, 1]

与问题没有直接关系的补充说明: 你的CitemCheck函数返回了一个指向int的指针, 但如果看一下它的调用方式, 似乎你想返回一个int值. 函数签名应该更像这样。

static int CitemCheck(PyObject *commandString, int commandStringLength)

(注意删除的 * int后)。)

以上是关于从python字符串中提取的C字符数组的主要内容,如果未能解决你的问题,请参考以下文章

python中如何从字符串内提取指定的字符

使用 Python 从 JSON 嵌套列表和字符串数组中提取值

如何从字符串中提取单词并将它们存储在c ++中的不同数组中

PHP 一个字符串,如何提取其中相同的字符?

JavaScript中如何提取字符串?

C++ - 从整数数组中插入和提取字符