str函数python嵌套int函数_将str作为int数组传递给Python C扩展函数(使用SWIG扩展)

如何将使用python代码获得的str值(包含3000 {‘0′,’1’}字节)作为参数传递给python c扩展函数(使用SWIG扩展),这需要int *(固定长度int数组)as输入参数?我的代码是这样的:

int *exposekey(int *bits) {

int a[1000];

for (int j=2000; j < 3000; j++) {

a[j - 2000] = bits[j];

}

return a;

}

我试过的是使用ctypes(见下面的代码):

import ctypes

ldpc = ctypes.cdll.LoadLibrary('./_ldpc.so')

arr = (ctypes.c_int * 3072)()

ldpc.exposekey(arr)

3072 {0,1}进入该位置. Python返回语法错误:超过255个参数.这仍然无法帮助我传递指定的str值而不是初始化的ctypes int数组.

其他建议包括使用SWIG字体图,但是如何将str转换为int *?提前致谢.

解决方法:

关于我的评论,这里有一些关于从函数返回数组的更多细节:[SO]: Returning an array using C.简而言之:方法处理:

>将返回的变量设为静态

>动态分配它(使用malloc(family)或new)

>将其转换为该函数的附加参数

可以通过两种方式获得在Python解释器中运行的那段C代码:

既然他们都在做同样的事情,将它们混合在一起毫无意义.因此,选择最适合您需求的产品.

ctypes

>这就是你的开始

>这是使用ctypes做事的方法之一

ctypes_demo.c:

#include

#if defined(_WIN32)

# define CTYPES_DEMO_EXPORT_API __declspec(dllexport)

#else

# define CTYPES_DEMO_EXPORT_API

#endif

CTYPES_DEMO_EXPORT_API int exposekey(char *bitsIn, char *bitsOut) {

int ret = 0;

printf("Message from C code...\n");

for (int j = 0; j < 1000; j++)

{

bitsOut[j] = bitsIn[j + 2000];

ret++;

}

return ret;

}

笔记:

>根据注释,我将函数中的类型从int *更改为char *,因为它的紧凑性要高4倍(尽管它仍然是700%效率低,因为每个char的7位被忽略,而只使用其中一个;可以修复,但需要按位处理)

>我拿了一个并转向第二个参数(bitsOut).我认为这是最好的,因为分配和取消分配数组是调用者的责任(从头开始的第3个选项)

>我还修改了索引范围(没有更改功能),因为使用低索引值并在一个地方添加内容更有意义,而不是高索引值并在另一个地方减去(相同)某些内容

>返回值是设置的位数(显然,在这种情况下为1000),但它只是一个示例

> printf它只是虚拟,以显示C代码被执行

>在处理此类数组时,建议也传递它们的维度,以避免出现超出范围的错误.此外,错误处理是一个重要方面

test_ctypes.py:

from ctypes import CDLL, c_char, c_char_p, c_int, create_string_buffer

bits_string = "010011000110101110101110101010010111011101101010101"

def main():

dll = CDLL("./ctypes_demo.dll")

exposekey = dll.exposekey

exposekey.argtypes = [c_char_p, c_char_p]

exposekey.restype = c_int

bits_in = create_string_buffer(b"\0" * 2000 + bits_string.encode())

bits_out = create_string_buffer(1000)

print("Before: [{}]".format(bits_out.raw[:len(bits_string)].decode()))

ret = exposekey(bits_in, bits_out)

print("After: [{}]".format(bits_out.raw[:len(bits_string)].decode()))

print("Return code: {}".format(ret))

if __name__ == "__main__":

main()

笔记:

> 1,我想提一下,运行代码并没有引发你得到的错误

>指定函数的argtypes和restype是必需的,也使事情变得更容易(在ctypes教程中记录)

>我打印bits_out数组(只有第一个 – 相关 – 部分,其余为0),以证明C代码完成了它的工作

>我在开始时用2000虚拟0初始化bits_in数组,因为这些值在这里不相关.此外,输入字符串(bits_string)长度不是3000个字符(原因很明显).如果你的bits_string是3000个字符长,你可以简单地初始化bits_in,如:bits_in = create_string_buffer(bits_string.encode())

>不要忘记将bits_out初始化为大小足够大的数组(在我们的示例中为1000),否则在尝试将其内容设置为超出大小时可能会出现段错误

>对于这个(简单)函数,ctypes变体更容易(至少对我而言,因为我不经常使用swig),但对于更复杂的函数/项目,它将变得过度杀伤并且转换为swig将是正确的去做

输出(在Win上运行Python3.5):

06002

swig

>几乎所有来自ctypes部分的内容也适用于此处

swig_demo.c:

#include

#include

#include "swig_demo.h"

char *exposekey(char *bitsIn) {

char *bitsOut = (char*)malloc(sizeof(char) * 1000);

printf("Message from C code...\n");

for (int j = 0; j < 1000; j++) {

bitsOut[j] = bitsIn[j + 2000];

}

return bitsOut;

}

swig_demo.i:

%module swig_demo

%{

#include "swig_demo.h"

%}

%newobject exposekey;

%include "swig_demo.h"

swig_demo.h:

char *exposekey(char *bitsIn);

笔记:

>这里我分配数组并返回它(从头开始的第二个选项)

> .i文件是标准的swig接口文件

>定义模块及其导出(通过%include)

>值得一提的是%newobject指令,它释放由expose键返回的指针,以避免内存泄漏

> .h文件只包含函数声明,以便被.i文件包含(它不是强制性的,但这样的方式更优雅)

>其余几乎是一样的

test_swig.py:

from swig_demo import exposekey

bits_in = "010011000110101110101110101010010111011101101010101"

def main():

bits_out = exposekey("\0" * 2000 + bits_in)

print("C function returned: [{}]".format(bits_out))

if __name__ == "__main__":

main()

笔记:

>从Python程序员的PoV开始,事情变得更有意义

>代码短得多(因为swig在幕后做了一些“魔术”):

> .i文件生成的包装器.c包装器文件大约为120K

> swig_demo.py生成的模块有~3K

>我在字符串的开头使用了与2000 0相同的技术

输出:

06007

3.普通的Python C API

>我将这部分作为个人练习加入

>这就是swig所做的,但是“手动”

capi_demo.c:

#include "Python.h"

#include "swig_demo.h"

#define MOD_NAME "capi_demo"

static PyObject *PyExposekey(PyObject *self, PyObject *args) {

PyObject *bitsInArg = NULL, *bitsOutArg = NULL;

char *bitsIn = NULL, *bitsOut = NULL;

if (!PyArg_ParseTuple(args, "O", &bitsInArg))

return NULL;

bitsIn = PyBytes_AS_STRING(PyUnicode_AsEncodedString(bitsInArg, "ascii", "strict"));

bitsOut = exposekey(bitsIn);

bitsOutArg = PyUnicode_FromString(bitsOut);

free(bitsOut);

return bitsOutArg;

}

static PyMethodDef moduleMethods[] = {

{"exposekey", (PyCFunction)PyExposekey, METH_VARARGS, NULL},

{NULL}

};

static struct PyModuleDef moduleDef = {

PyModuleDef_HEAD_INIT, MOD_NAME, NULL, -1, moduleMethods

};

PyMODINIT_FUNC PyInit_capi_demo(void) {

return PyModule_Create(&moduleDef);

}

笔记:

>它需要swig_demo.h和swig_demo.c(不要在这里复制它们的内容)

>它只适用于Python 3(实际上我有一些令人头疼的事情让它起作用,特别是因为我习惯了不再存在的PyString_AsString)

>错误处理很差

> test_capi.py与test_swig.py类似,但有一个(显而易见的)区别:来自swig_demo的import expose键应替换为capi_demo import exposekey

>输出也与test_swig.py相同(同样,这里不会复制它)

标签:python,arrays,string,int,swig

你可能感兴趣的:(str函数python嵌套int函数_将str作为int数组传递给Python C扩展函数(使用SWIG扩展))