如何将使用python代码获取的str
值(包含3000 {'0','1'}字节)作为参数传递给python c扩展函数(使用SWIG扩展),这需要{{ 1}}(固定长度的int数组)作为输入参数?我的代码是这样的:
int *
我尝试过使用int *exposekey(int *bits) {
int a[1000];
for (int j=2000; j < 3000; j++) {
a[j - 2000] = bits[j];
}
return a;
}
(见下面的代码):
ctypes
以3072 {0,1}进入该位置。 Python返回语法错误:超过255个参数。这仍然无法帮助我传递指定的str值而不是初始化的import ctypes
ldpc = ctypes.cdll.LoadLibrary('./_ldpc.so')
arr = (ctypes.c_int * 3072)(<mentioned below>)
ldpc.exposekey(arr)
int数组。
其他建议包括使用SWIG字体图,但如何将str转换为ctypes
?提前谢谢。
答案 0 :(得分:1)
关于我的评论,这里有一些关于从函数返回数组的更多细节:[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倍(尽管它仍然 ~700 %效率低,因为每个char的7位被忽略,而只使用其中一个;可以修复,但需要按位处理)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]
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);
}
备注强>:
from swig_demo import exposekey
应替换为from capi_demo import exposekey