Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/321.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从Python到C的bytearray传输并返回_Python_C - Fatal编程技术网

从Python到C的bytearray传输并返回

从Python到C的bytearray传输并返回,python,c,Python,C,我需要快速处理XOR字节数组, 在Python的一个变体中 for i in range(len(str1)): str1[i]=str1[i] ^ 55 工作非常慢 我用C写了这个模块。 我对C语言非常了解,在我写任何东西之前。 变型 PyArg_ParseTuple (args, "s", &str)) 一切都按预期工作,但我需要使用s而不是s*,因为元素可以包含嵌入的null,但如果在调用python崩溃时将s更改为s* PyArg_ParseTuple (args, "s*"

我需要快速处理XOR字节数组, 在Python的一个变体中

for i in range(len(str1)): str1[i]=str1[i] ^ 55
工作非常慢
我用C写了这个模块。 我对C语言非常了解,在我写任何东西之前。
变型

PyArg_ParseTuple (args, "s", &str))
一切都按预期工作,但我需要使用s而不是s*,因为元素可以包含嵌入的null,但如果在调用python崩溃时将s更改为s*

PyArg_ParseTuple (args, "s*", &str)) // crash
也许像我这样的初学者想用我的例子开始写自己的东西,所以把这个例子中用到的所有信息都带到Windows上。
在页面上解析参数和构建值

测试\u xor.c

#include <Python.h>

static PyObject* fast_xor(PyObject* self, PyObject* args)
{
    const char* str ;
    int i;

    if (!PyArg_ParseTuple(args, "s", &str))
        return NULL;

    for(i=0;i<sizeof(str);i++) {str[i]^=55;};
    return Py_BuildValue("s", str);

}

static PyMethodDef fastxorMethods[] =
{
     {"fast_xor", fast_xor, METH_VARARGS, "fast_xor desc"},
     {NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC

initfastxor(void)
{
     (void) Py_InitModule("fastxor", fastxorMethods);
}
compile.bat

rem use http://bellard.org/tcc/
tiny_impdef.exe C:\Python26\python26.dll
tcc -shared test_xor.c python26.def -IC:\Python26\include -LC:\Python26\libs -ofastxor.pyd
test_xor.py 
试一试


不确定缓冲区大小要求是什么-我假设1024是足够的。

不要使用
作为
循环。改用a,它们的速度要快得多:

In [1]: import random

In [2]: t = bytearray([random.randint(0,255) for i in xrange(10000)])

In [3]: u = bytearray([b^55 for b in t])
这非常快:

In [11]: %timeit u = bytearray([b^55 for b in t])
1000 loops, best of 3: 1.36 ms per loop
这并不慢。对于1MB(10*6字节),大约需要130ms


当然,正如Henry Gomersall所回答的那样,使用numpy是更好的解决方案。

使用numpy可以很快做到这一点。在C中手动运行自己的xor例程不太可能快得多:

In [1]: import numpy

In [2]: data = numpy.uint8(numpy.random.randint(0, 256, 10000))

In [3]: timeit xor_data = numpy.bitwise_xor(data, 55)
100000 loops, best of 3: 17.4 us per loop
如果您使用的是一个大数据集(比如1亿个点),那么它可以与您为代码引用的时间相媲美:

In [12]: data = numpy.uint8(numpy.random.randint(0, 256, 100000000))

In [13]: timeit xor_data = numpy.bitwise_xor(data, 55)
1 loops, best of 3: 198 ms per loop

您不需要构建扩展模块来快速完成这项工作,您可以使用NumPy。但对于您的问题,您需要一些c代码,如下所示:

#include <Python.h>
#include <stdlib.h> 

static PyObject * fast_xor(PyObject* self, PyObject* args)
{
    const char* str;
    char * buf;
    Py_ssize_t count;
    PyObject * result;
    int i;

    if (!PyArg_ParseTuple(args, "s#", &str, &count))
    {
        return NULL;
    }

    buf = (char *)malloc(count);

    for(i=0;i<count;i++)
    {
        buf[i]=str[i] ^ 55;
    }

    result = Py_BuildValue("s#", buf, count);
    free(buf);
    return result;
}

另一种方法是使用。下面的模块为支持缓冲区协议的任何对象定义了
fast\u xor
,为具有可写缓冲区的对象定义了
fast\u xor\u inplace
,例如
bytearray
。此版本返回
None
。我还添加了第二个
unsigned char
参数,默认值为55

例如:

>>> s = 'abc'
>>> b = bytearray(s)
>>> fast_xor(s), fast_xor(s, 0x20)
('VUT', 'ABC')
>>> fast_xor_inplace(b, 0x20)
>>> b
bytearray(b'ABC')

>>> fast_xor_inplace(s)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
BufferError: Object is not writable.

>>> fast_xor(b, 256)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: unsigned byte integer is greater than maximum
>s='abc'
>>>b=字节数组(s)
>>>快速异或,快速异或,0x20
(“VUT”、“ABC”)
>>>快速异或就地(b,0x20)
>>>b
bytearray(b'ABC')
>>>快速异或就地
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
BufferError:对象不可写。
>>>快速异或(b,256)
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
溢出错误:无符号字节整数大于最大值
资料来源:

#include <Python.h>

static PyObject *fast_xor_inplace(PyObject *self, PyObject *args)
{
    PyObject *arg1;
    unsigned char arg2 = 55;
    Py_buffer buffer;
    char *buf;
    int i;

    if (!PyArg_ParseTuple(args, "O|b:fast_xor_inplace", &arg1, &arg2))
        return NULL;

    if (PyObject_GetBuffer(arg1, &buffer, PyBUF_WRITABLE) < 0)
        return NULL;

    buf = buffer.buf;
    for(i=0; i < buffer.len; i++)
        buf[i] ^= arg2;

    PyBuffer_Release(&buffer);
    Py_INCREF(Py_None);
    return Py_None;
}

static PyObject *fast_xor(PyObject *self, PyObject *args)
{
    PyObject *arg1;
    unsigned char arg2 = 55;
    PyObject *result;
    Py_buffer buffer;
    char *buf, *str;
    int i;

    if (!PyArg_ParseTuple(args, "O|b:fast_xor", &arg1, &arg2))
        return NULL;

    if (PyObject_GetBuffer(arg1, &buffer, PyBUF_SIMPLE) < 0)
        return NULL;

    result = PyString_FromStringAndSize(NULL, buffer.len);
    if (result == NULL)
        return NULL;

    buf = buffer.buf;
    str = PyString_AS_STRING(result);
    for(i=0; i < buffer.len; i++)
        str[i] = buf[i] ^ arg2;

    PyBuffer_Release(&buffer);
    return result;
}

static PyMethodDef fastxorMethods[] =
{
     {"fast_xor", fast_xor, METH_VARARGS, "fast xor"},
     {"fast_xor_inplace", fast_xor_inplace, METH_VARARGS, "fast inplace xor"},
     {NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC
initfastxor(void)
{
    Py_InitModule3("fastxor", fastxorMethods, "fast xor functions");
}
#包括
静态PyObject*fast\uxor\u就地(PyObject*self,PyObject*args)
{
PyObject*arg1;
无符号字符arg2=55;
Py_缓冲区;
char*buf;
int i;
if(!PyArg_ParseTuple(args,“O|b:fast_xor_inplace”、&arg1和&arg2))
返回NULL;
if(PyObject_GetBuffer(arg1,&buffer,PyBUF_可写)<0)
返回NULL;
buf=buffer.buf;
对于(i=0;i
My datasize 10-100 MB,在我的示例中,您的采样时间为3-30秒(带有struct.unpack和zlib 0.6-6秒等提示)。在我的C示例中,我达到了时间0.06-0.6秒。这是值得的。我最初的时间每次都包括设置。见修改后的答案。10 MB需要1.3秒。这还值得吗?你可以删除内部列表,它会更快<[4]中的code>1000个循环,最好是每个循环3:605个字节。@BurhanKhalid:您的内部bytearray只有255字节,而不是10000字节。我猜这就是为什么它更快的原因。我已经测试过有列表和没有列表,列表的速度更快。@Roland Smith,你的版本是最快的简单版本。但是,在带有C代码的示例中,结果是0.006秒/1MBytes。这比您的结果0.13秒/1字节要好。在纯python中,我使用struct.unpack的最佳结果是0.06秒/1MBytes,我事先不知道将要传递的bytearray的大小。我必须用PyArg_ParseTuple
获取范围内I的大小(len(str1)):
应该是str1中I的
除非它看起来是写入的,它正在写回数组。虽然这也有一个错误:
str1=str1[i]^55
应该是
str1[i]=str1[i]^55
,或者更简洁地说是
str[1]^=55
。感谢Henry Gomershal,更正了是的,它仍然有效,如何实现类似的功能。b=bytearray('World')def change(b):对于范围内的i(len(b)):b[i]=b[i]^55MYou可以使用bytearray API:,来获取长度和char*缓冲区指针。用
s*
排序:声明必须
Py\u buffer str
,解析必须
PyArg\u parsertuple(args,“s*”,&str)
,使用:
str.len
-缓冲区长度,
str.buf
-数据。谢谢大家。工作对我来说非常有吸引力,除了我需要将输出类型更改为“y”,因为UnicodeDecodeError。结果=Py#u构建值(“y#”,buf,count);是的,非常好用,谢谢。我开始了解如何使用Py_缓冲区。但奇怪的是,如果我运行examle作为example.py,所有的工作都很好。如果我在控制台中一步一步地运行-step
fastxor.fast\u xor\u inplace(b,0x20)
导致python崩溃。定义“崩溃”吗?你有什么毛病吗?@Ar
In [1]: import fastxor

In [2]: a = "abcdsafasf12q423\0sdfasdf"

In [3]: fastxor.fast_xor(a)
Out[3]: 'VUTSDVQVDQ\x06\x05F\x03\x05\x047DSQVDSQ'


In [5]: import numpy as np

In [6]: (np.frombuffer(a, np.int8)^55).tostring()
Out[6]: 'VUTSDVQVDQ\x06\x05F\x03\x05\x047DSQVDSQ'

In [7]: a = a*10000

In [8]: %timeit fastxor.fast_xor(a)
1000 loops, best of 3: 877 us per loop

In [15]: %timeit (np.frombuffer(a, np.int8)^55).tostring()
1000 loops, best of 3: 1.15 ms per loop
>>> s = 'abc'
>>> b = bytearray(s)
>>> fast_xor(s), fast_xor(s, 0x20)
('VUT', 'ABC')
>>> fast_xor_inplace(b, 0x20)
>>> b
bytearray(b'ABC')

>>> fast_xor_inplace(s)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
BufferError: Object is not writable.

>>> fast_xor(b, 256)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: unsigned byte integer is greater than maximum
#include <Python.h>

static PyObject *fast_xor_inplace(PyObject *self, PyObject *args)
{
    PyObject *arg1;
    unsigned char arg2 = 55;
    Py_buffer buffer;
    char *buf;
    int i;

    if (!PyArg_ParseTuple(args, "O|b:fast_xor_inplace", &arg1, &arg2))
        return NULL;

    if (PyObject_GetBuffer(arg1, &buffer, PyBUF_WRITABLE) < 0)
        return NULL;

    buf = buffer.buf;
    for(i=0; i < buffer.len; i++)
        buf[i] ^= arg2;

    PyBuffer_Release(&buffer);
    Py_INCREF(Py_None);
    return Py_None;
}

static PyObject *fast_xor(PyObject *self, PyObject *args)
{
    PyObject *arg1;
    unsigned char arg2 = 55;
    PyObject *result;
    Py_buffer buffer;
    char *buf, *str;
    int i;

    if (!PyArg_ParseTuple(args, "O|b:fast_xor", &arg1, &arg2))
        return NULL;

    if (PyObject_GetBuffer(arg1, &buffer, PyBUF_SIMPLE) < 0)
        return NULL;

    result = PyString_FromStringAndSize(NULL, buffer.len);
    if (result == NULL)
        return NULL;

    buf = buffer.buf;
    str = PyString_AS_STRING(result);
    for(i=0; i < buffer.len; i++)
        str[i] = buf[i] ^ arg2;

    PyBuffer_Release(&buffer);
    return result;
}

static PyMethodDef fastxorMethods[] =
{
     {"fast_xor", fast_xor, METH_VARARGS, "fast xor"},
     {"fast_xor_inplace", fast_xor_inplace, METH_VARARGS, "fast inplace xor"},
     {NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC
initfastxor(void)
{
    Py_InitModule3("fastxor", fastxorMethods, "fast xor functions");
}