gpt4 book ai didi

python - 如何在 ctypes 中传回指针?

转载 作者:太空狗 更新时间:2023-10-29 21:18:44 27 4
gpt4 key购买 nike

不太了解 ctypes,最近才开始使用它。

我在类似 C 的 dll 中有一个简单的函数,它返回一个指向动态生成的字符串的指针。
它工作正常,但是,因为我手动为字符串分配内存,所以我应该在使用后释放它。

我有这样的东西:

extern "C" char* DLL_EXPORT func(const char* str1, const char* str2)
{
return getSomeString(str1, str2);
}

// Goal is to call this function correctly from Python.
extern "C" void DLL_EXPORT freeMem(void *mem)
{
if(mem!=NULL)
delete mem;
}

但我不知道,如何在 Python 中将接收到的指针传回以进行删除?

最佳答案

通常,您在 ctypes 中使用的每个函数都应该声明其参数和返回类型,以便 Python 可以检查参数的正确数量和类型,并将 Python 对象参数转换为正确的 C 数据对象。不幸的是,在这种情况下,func 的正常返回值将是 c_char_p,但 ctypes 试图提供帮助并将 c_char_p 将值返回到 Python 字符串,无法访问原始 C 指针值。相反,您可以将返回类型声明为 POINTER(c_char) 并使用 cast 来检索字符串值,从而使返回值为 LP_c_char可以释放的对象。

这是一个例子。请注意,声明正确的 .restype 对于 64 位 Python 尤其重要,因为默认返回类型是 c_int(32 位),而 64 位指针可能是截断。此代码已针对 32 位和 64 位版本进行了测试。

测试.c

#include <string.h>
#include <stdlib.h>

#ifdef _WIN32
# define API __declspec(dllexport)
#else
# define API
#endif

API char* func(const char* str1, const char* str2) {
size_t len = strlen(str1) + strlen(str2) + 1;
char* tmp = malloc(len);
strcpy_s(tmp, len, str1);
strcat_s(tmp, len, str2);
return tmp;
}

API void freeMem(void *mem) {
free(mem);
}

测试.py

import ctypes as ct

dll = ct.CDLL('./test')
dll.func.argtypes = ct.c_char_p,ct.c_char_p
dll.func.restype = ct.POINTER(ct.c_char)
dll.freeMem.argtypes = ct.c_void_p,
dll.freeMem.restype = None

# Helper function to extract the return value as a Python object
# and always free the pointer.
def freeMem(a,b):
p = dll.func(b'abcdef', b'ghijkl')
print(p)
s = ct.cast(p, ct.c_char_p).value
dll.freeMem(p)
return s

print(freeMem(b'abcdef', b'ghijkl'))

输出:

<ctypes.LP_c_char object at 0x00000279D7959DC0>
b'abcdefghijkl'

关于python - 如何在 ctypes 中传回指针?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13908226/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com