c++ - Python ctypes : how to free memory? 获取无效指针错误

标签 c++ python c ctypes

我想从带有 ctypes 的 C/C++ 库中获取一些字符串到 python 中。我的代码如下所示:

lib 中的代码:

const char* get(struct something *x) 
{
    [...]
    // buf is a stringstream
   return strdup(buf.str().c_str());
}

void freeme(char *ptr)
{
    free(ptr);
}

Python 代码:

fillprototype(lib.get, c_char_p, POINTER(some_model)])
fillprototype(lib.freeme, None, [c_char_p])

// what i want to do here: get a string into python so that i can work
// with it and release the memory in the lib.
c_str = lib.get(some_model)
y = ''.join(c_str)
lib.freeme(c_str) 

如果我 print() c_str,一切都在那里。问题出在(或似乎是)在 Python 的最后一行。我无法释放内存 - 库得到了错误的指针。我在这里做错了什么? (请不要建议 boost::python 左右)。

*** glibc detected *** python2: munmap_chunk(): invalid pointer: 0x00000000026443fc ***

最佳答案

正如 David Schwartz 所指出的,如果将 restype 设置为 c_char_p,ctypes 会返回一个常规的 Python 字符串对象。解决此问题的一种简单方法是使用 void * 并转换结果:

字符串.c:

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

char *get(void)
{
    char *buf = "Hello World";
    char *new_buf = strdup(buf);
    printf("allocated address: %p\n", new_buf);
    return new_buf;
}

void freeme(char *ptr)
{
    printf("freeing address: %p\n", ptr);
    free(ptr);
}

Python 用法:

from ctypes import *

lib = cdll.LoadLibrary('./string.so')
lib.freeme.argtypes = c_void_p,
lib.freeme.restype = None
lib.get.argtypes = []
lib.get.restype = c_void_p

>>> ptr = lib.get()
allocated address: 0x9facad8
>>> hex(ptr)
'0x9facad8'
>>> cast(ptr, c_char_p).value
'Hello World'
>>> lib.freeme(ptr)
freeing address: 0x9facad8

您也可以使用 c_char_p 的子类。事实证明,ctypes 不会为简单类型的子类调用 getfunc

class c_char_p_sub(c_char_p):
    pass

lib.get.restype = c_char_p_sub

value 属性返回字符串。您可以将 freeme 的参数保留为更通用的 c_void_p。它接受任何指针类型或整数地址。

关于c++ - Python ctypes : how to free memory? 获取无效指针错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13445568/

相关文章:

c++ - 将字符串 vector 与字符串进行比较

c++ - 删除 vector 大小为 0 的结构 vector 的所有元素

c++ - 使用 GCC 编译 C++ 程序

c++ - 用于 C/C++ 开发的 Mac 与 Ubuntu?

python - 使用 ElementTree 跟踪父元素

python - 如何使用 Google BigQuery python API 获得超过 100,000 个响应结果?

c - GCC 的 __attribute__((__packed__)) 是否保留原始顺序?

python - 使用问题标记提取已知两个标记之间的子字符串

c - C 中数组中的 int 不断变为零

c - epoll中区分文件描述符类型