如何将str
使用 python 代码获得的值(包含 3000 {'0', '1'} 个字节)作为参数传递给需要int *
(固定长度 int 数组)作为输入参数的 python c 扩展函数(使用 SWIG 扩展)? 我的代码是这样的:
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)(<mentioned below>)
ldpc.exposekey(arr)
在该位置输入 3072 {0, 1}。Python 返回语法错误:超过 255 个参数。这仍然不能帮助我传递分配的 str 值而不是初始化的ctypes
int 数组。
其他建议包括使用 SWIG 类型映射,但是如何将 str 转换为int *
?提前致谢。
关于我的评论,这里有一些关于从函数返回数组的更多细节:[SO]: Returning an array using C。简而言之:处理这个的方法:
可以通过两种方式让那段C代码在Python解释器中运行:
因为他们都在做同样的事情,所以将它们混合在一起是没有意义的。因此,请选择最适合您需求的一种。
ctypes_demo.c :
#include <stdio.h>
#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 倍(尽管由于每个字符的 7 位被忽略而效率仍然低到700%,而只使用其中之一;这可以修复,但是需要按位处理)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()
注意事项:
bits_in = create_string_buffer(bits_string.encode())
输出(在Win上使用Python3.5运行):
c:\Work\Dev\StackOverflow\q47276327>"c:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" test_ctypes.py Before: [ ] Message from C code... After: [010011000110101110101110101010010111011101101010101] Return code: 1000
swig_demo.c :
#include <malloc.h>
#include <stdio.h>
#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);
注意事项:
%include
)%newobject
释放exposekey返回的指针以避免内存泄漏的指令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()
注意事项:
输出:
c:\Work\Dev\StackOverflow\q47276327>"c:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" test_swig.py Message from C code... C function returned: [010011000110101110101110101010010111011101101010101]
capo_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);
}
注意事项:
from swig_demo import exposekey
应替换为from capi_demo import exposekey
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句