关于我的评论,以下是有关从函数返回数组的更多详细信息:
[SO]: Returning an array using C
. 简而言之:处理方法:
-
生成返回的变量
静止的
-
马洛克
(家庭)或
新
-
将其转换为函数的附加参数
得到那块
C
要在中运行的代码
蟒蛇
口译员有两种可能:
因为他们都在做同一件事,把他们混在一起是没有意义的。所以,选择一个最适合你需要的。
C类型
ctypes\u演示。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%
效率低下,因为每个字符的7位被忽略,而只使用其中一位;这可以修复,但需要
按位
处理)
-
我拿走了
一
然后变成了2
nd公司
参数(
比特苏特
). 我认为这是最好的,因为调用方负责分配和取消分配阵列(3
rd
选项)
-
我还修改了索引范围(没有更改功能),因为处理低索引值并在一个位置向其添加一些内容更有意义,而不是在高索引值并在另一个位置减去(相同)一些内容
-
返回值是设置的位数(显然,在本例中为1000),但这只是一个示例
-
打印F
这只是一个假人,以表明
C
-
在处理此类数组时,建议也传递其维数,以避免越界错误。而且
错误处理
是一个重要方面
测试类型。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
和
重新键入
是
C类型
教程)
-
我正在打印
bits\u输出
数组(与其他部分一样,仅第一部分和相关部分)
0
)为了证明
C
代码完成了它的工作
-
bits\U in
2000虚拟阵列
0
bits\U字符串
)不是3000个字符长(出于明显的原因)。如果你的
bits\U字符串
3000个字符长,您可以简单地初始化
bits\U in
例如:
bits_in = create_string_buffer(bits_string.encode())
-
不要忘记
初始化
bits\u输出
对于大小足够大(在我们的示例中为1000)的阵列,否则
segfault
当试图将其内容设置为超过大小时可能会出现
-
对于此(简单)函数
C类型
变体更容易(至少对我来说,因为我不使用
swig公司
通常情况下),但对于更复杂的功能/项目,这将成为一种过度使用,并切换到
swig公司
是正确的选择
输出
(与一起运行
蟒蛇3.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
2.
swig公司
swig_演示。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_演示。一、
:
%module swig_demo
%{
#include "swig_demo.h"
%}
%newobject exposekey;
%include "swig_demo.h"
swig_演示。h
:
char *exposekey(char *bitsIn);
:
-
在这里,我分配数组并返回它(2
nd公司
选项)
-
这个
.一、
文件是标准
swig公司
接口文件
-
%include
-
值得一提的是
%newobject
指令,该指令取消分配由返回的指针
exposekey公司
避免内存泄漏
-
这个
.h
文件只包含函数声明,以便包含在
.一、
文件(这不是强制性的,但这样做更优雅)
-
测试开关。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()
笔记
:
-
事情变得更有意义
蟒蛇
程序员的
PoV
-
代码要短得多(这是因为
swig公司
在幕后做了一些“魔术”:
-
包装纸
.c
.一、
文件已
约12万
-
这个
swig_演示。py公司
生成的模块具有
约3K
-
我对2000使用了相同的技术
输出
:
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]
3、普通
Python C API
-
我添加这部分作为个人练习
-
这是什么
swig公司
但“手动”
capi_演示。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_演示。h
和
(此处不复制其内容)
-
它
Python 3
(事实上,我很头疼,尤其是因为我习惯了
不再存在)
-
错误处理较差
-
测试capi。py公司
类似于
测试开关。py公司
有一个(明显的)区别:
from swig_demo import exposekey
应替换为
from capi_demo import exposekey
-
输出也与
测试开关。py公司
(再说一次,这里不重复)