17

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 ***
4

2 に答える 2

32

David Schwartzが指摘したように、restypeをに設定するとc_char_p、ctypesは通常のPython文字列オブジェクトを返します。これを回避する簡単な方法は、を使用しvoid *て結果をキャストすることです。

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_pgetfuncctypesは単純型のサブクラスを呼び出さないことがわかりました。

class c_char_p_sub(c_char_p):
    pass

lib.get.restype = c_char_p_sub

value属性は文字列を返します。のパラメータはfreeme、より一般的なもののままにしておくことができますc_void_p。これは、任意のポインタ型または整数アドレスを受け入れます。

于 2012-11-19T11:04:45.980 に答える
-1

メモリを解放するための安価なハックは、Cで静的にメモリを割り当て、決して解放しないことです。もちろん、必要な最大量がわかっている場合、およびルーチンへの2回目の呼び出しの前にそれが完了していることがわかっている場合にのみ機能します。

static char _externalStringBuffer[MAX_BUFFER_SIZE];
char *get() {
    // put characters in _externalStringBuffer
    return _externalStringBuffer;
}
于 2018-03-20T23:53:42.277 に答える