Python的ctypes的:如何释放内存?获取无效指针错误 [英] Python ctypes: how to free memory? Getting invalid pointer error

查看:4890
本文介绍了Python的ctypes的:如何释放内存?获取无效指针错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从与ctypes的蟒蛇成一个C / C ++库的一些字符串。我的code是这样的:

code在lib目录下:

 为const char *得到(结构的东西* X)
{
    [...]
    // buf是一个字符串流
   返回的strdup(buf.str()c_str());
}无效freeme(字符* PTR)
{
    免费(PTR);
}

Python的code:

  fillprototype(lib.get,c_char_p,指针(some_model)])
fillprototype(lib.freeme,无,[c_char_p])//我想在这里做的:得到一个字符串到Python这样我可以工作
它//并在lib释放内存。
c_str = lib.get(some_model)
Y =''。加入(c_str)
lib.freeme(c_str)

如果我打印()c_str,一切都在那里。问题是(或似乎是),在过去的Python线。我不能释放内存 - 库越来越错误的指针。什么我做错了吗? (也请不要暗示的boost ::蟒蛇左右)。

  *** glibc的检测*** python2:munmap_chunk():无效的指针:0x00000000026443fc ***


解决方案

当大卫·施瓦茨指出,如果设置restype为 c_char_p ,ctypes的返回一个普通的Python字符串对象。一个简单的方法来解决这个问题是使用无效* 和铸铁的结果是:

string.c:

 的#include<&stdlib.h中GT;
#包括LT&;&string.h中GT;
#包括LT&;&stdio.h中GT;字符* GET(无效)
{
    字符* BUF =Hello World的;
    字符* new_buf =的strdup(BUF);
    的printf(分配地址:%P \\ N,new_buf);
    返回new_buf;
}无效freeme(字符* PTR)
{
    的printf(解放地址:%P \\ N,PTR);
    免费(PTR);
}

Python的用法:

 从ctypes的导入*LIB = cdll.LoadLibrary('./ string.so')
lib.freeme.argtypes = c_void_p,
lib.freeme.restype =无
lib.get.argtypes = []
lib.get.restype = c_void_p>>> PTR = lib.get()
分配的地址:0x9facad8
>>>十六进制(PTR)
0x9facad8
>>> CAST(PTR,c_char_p).value的
'你好,世界'
>>> lib.freeme(PTR)
解放地址:0x9facad8


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

 类c_char_p_sub(c_char_p):
    通过lib.get.restype = c_char_p_sub

属性返回字符串。你可以离开 freeme 的参数作为更通用 c_void_p 。接受任何指针类型或整数地址。

I want to get some string from a C/C++ library with ctypes into python. My code looks like this:

Code in lib:

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

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

Python code:

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) 

If i print() c_str, everything is there. Problem is (or seems to be) in the last Python line. I cannot free the memory - the library is getting a wrong pointer. What I am doing wrong here? (And please don't suggest boost::python or so).

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

解决方案

As David Schwartz pointed out, if you set restype to c_char_p, ctypes returns a regular Python string object. A simple way to get around this is to use a void * and cast the result:

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 usage:

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


You can also use a subclass of c_char_p. It turns out that ctypes doesn't call the getfunc for a subclass of a simple type.

class c_char_p_sub(c_char_p):
    pass

lib.get.restype = c_char_p_sub

The value attribute returns the string. You can leave the parameter for freeme as the more generic c_void_p. That accepts any pointer type or integer address.

这篇关于Python的ctypes的:如何释放内存?获取无效指针错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆