将字节字符串从Python传递到C

将字节字符串从Python传递到C,python,c,python-3.x,python-c-api,python-extensions,Python,C,Python 3.x,Python C Api,Python Extensions,我正在用C编写一个python扩展,并试图将一个bytes对象传递给我的函数。显然,'s'标记用于字符串;我试过“O”、“N”和其他几个词,但都没有成功。是否有令牌可用于解析字节对象?如果没有,是否有其他方法来解析字节对象 static PyObject *test(PyObject *self, PyObject *args) { char *dev; uint8_t *key; if(!PyArg_ParseTuple(args, "ss", &dev, &

我正在用C编写一个python扩展,并试图将一个bytes对象传递给我的函数。显然,'s'标记用于字符串;我试过“O”、“N”和其他几个词,但都没有成功。是否有令牌可用于解析字节对象?如果没有,是否有其他方法来解析字节对象

static PyObject *test(PyObject *self, PyObject *args)
{
    char *dev;
    uint8_t *key;

    if(!PyArg_ParseTuple(args, "ss", &dev, &key))
        return NULL;

    printf("%s\n", dev);

    for (int i = 0; i < 32; i++)
    {
          printf("Val %d: %d\n", i, key[i]);
    }

    Py_RETURN_NONE;
}
静态PyObject*测试(PyObject*self,PyObject*args)
{
char*dev;
uint8_t*键;
if(!PyArg_ParseTuple(args、ss、&dev、&key))
返回NULL;
printf(“%s\n”,dev);
对于(int i=0;i<32;i++)
{
printf(“Val%d:%d\n”,i,键[i]);
}
Py_返回_无;
}
从python调用:
test(“device”,f.read(32))
如果您阅读了

s
仅用于从
str
对象获取以
NUL
结尾的UTF-8编码的C样式字符串(因此它适用于第一个参数,但不适用于第二个参数)

y*
在文件中特别指出(原文强调):

这是接受二进制数据的推荐方法。


y#
也可以工作,代价是要求调用方提供不可变的
字节
类对象,不包括
bytearray
mmap.mmap

之类的对象。如果使用Python 3,测试函数调用中的第一个参数是unicode字符串,而不是字节字符串。您需要编写
b“设备”
。不,第一个参数应该是包含设备名称的Unicode字符串。第二个参数是作为字节对象从文件中读入的加密密钥;但是,它在
过程的循环结束后终止,退出代码为139(被信号11:SIGSEGV中断)
。有什么原因吗?@DanielCopley:在循环之后?如果在输入数组的边界之外读取,您编写的代码可能会出现seg错误,但这不太可能。我不知道一旦你使用了缓冲器,会发生什么变化;你基本上是在要求心理调试。Segfaults表示您试图读取或写入未映射到内存空间的地址,但除此之外没有说明什么。我想我可能使用了
Py\u缓冲区
类型不正确?我将
y*
切换到
y
(它返回一个字符指针,而不是
Py\u buffer
),这似乎解决了我的问题。不确定这种方法是否有缺陷。@DanielCopley:原始二进制数据往往包含
NUL
字节。如果您不使用
y*
y#
,您就不知道数据的实际长度是多少,并且可能会在到达末尾之前停止。@DanielCopley:“确切地知道长度”并将其弄错,这意味着您会出错,或者完全胡说八道,而不是能够引发有用的异常,这是一个问题。在您依赖调用方数据的那一刻,您就不应该编写那些假设会在没有有用诊断的情况下使程序崩溃的代码。这对维护人员来说也是一种误导,他们可以并且会合理地认为
y
意味着“
NUL
-终止字节字符串”,因为这是它的唯一合法使用。