0

I'm playing a bit with python ctypes, probably someone could tell me some elegant way to handle an exported buffer created in C with a malloc.

So, it's a very stupid c code that could explain what I'm looking for.

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

char * stringa;
int numero = 0;
int * numero_2;

void crea_variabili_dyn() {

    if ( numero_2 == NULL) {
        numero_2 = malloc(1 * sizeof(int));
        *numero_2 = 2;        
        }

    }


void incrementa() {

    numero += 1;
    *numero_2 += 11;
    }


void ciao() {

    crea_variabili_dyn();
    stringa = "cane.huu";
    incrementa();
    printf("%d\n", numero);
    printf("%d\n", *numero_2);    
    printf("%s\n", stringa);
    incrementa();
    printf("%d\n", numero);
    printf("%d\n", *numero_2);    
    printf("%s\n", stringa);
}



void main (void) {

    //printf("%d\n", numero);
    ciao();
    //printf("%d\n", numero);

}

I compile it: gcc -shared -o playing_ctypes.so playing_ctypes.c

and then I play it with python:

import ctypes

testlib = ctypes.CDLL('/home/gnommaro/Dev/C/playing_ctypes.so')

c_numero = ctypes.c_int.in_dll(testlib, "numero")
c_numero_2 = ctypes.c_int.in_dll(testlib, "numero_2")

c_numero
c_numero_2

testlib.ciao()

c_numero
c_numero_2

As used to know c_numero is a integer and when called from python terminal it returns c_long(54)

Meanwhile c_numero_2 is a buffer allocated dynamically and when it's called it returns c_void_p(147438576) or c_long(147438576)

It depend byt the declared ctypes export type.

私が呼び出すとtestlib.ciao()すべてがうまくいきますが、これらの ctypes 整数のいずれかの値をインクリメント、デクリメント、または単に任意に変更したい場合は、次の方法でオーバーライドできます。

c_numero.value = 89

整数について見たように、非常にうまく機能します。しかし、malloced variablec_number_2の場合、属性.valueはバッファのアドレス (?) を返し、その中の値 (整数) を変更したい場合はどうすればよいでしょうか?

または、他の世界では、ctypes を使用してポインターをエクスポートし、そのコンテンツ値をエレガントな方法で操作するにはどうすればよいでしょうか。

おそらくmemcpy、ある種の python.ctypes ハンドラーを使用するか作成するでしょうが、最初にいくつかの醜いハードコーディングを作成するために、あなたの助けを求める必要があります。

ありますか?:)

4

3 に答える 3

2

C と同じように ctypes ポインターにインデックスを付けることができますが、C と同じように、バッファーの末尾を超えて書き込むことはできません。

from ctypes import *

dll = CDLL('msvcrt')
dll.malloc.restype = c_void_p
n = dll.malloc(5 * sizeof(c_int))
n = cast(n,POINTER(c_int))
for i in range(5):
    print('uninitialized value',n[i])
    n[i] = i
    print('new value',n[i])

出力:

uninitialized value 6815752
new value 0
uninitialized value 0
new value 1
uninitialized value 6128720
new value 2
uninitialized value 0
new value 3
uninitialized value 0
new value 4

キャストをスキップするために malloc の restype について嘘をつくことができることに注意してください。

dll.malloc.restype = POINTER(c_int)

グローバル変数には次のようにアクセスできます。

c_numero_2 = POINTER(c_int).in_dll(testlib, "numero_2")
c_numero_2[0] = 1
c_numero_2[1] = 2
于 2012-11-25T20:35:26.000 に答える
0

これは間違いなくこれを行うための最もエレガントな方法です:

c_numero_2_content  = (ctypes.c_long).from_address(c_numero_2.value) 
于 2012-11-25T19:04:26.007 に答える
0

わかりました、3行のコードで私はトリックを行うことができたようです

c_long_p = ctypes.POINTER(ctypes.c_long)
c_numero_2_ptr = ctypes.cast(c_numero_2.value, c_long_p)
c_numero_2_ptr.content 

それだけです:)乾杯

于 2012-11-25T18:18:07.873 に答える