Python CTYPE:如何释放内存?获取无效的指针错误

发布于 2021-01-29 18:00:22

我想从带有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 ***
关注者
0
被浏览
150
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

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

    string.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。那可以接受任何指针类型或整数地址。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看