我正在玩python ctypes,可能有人可以告诉我一些优雅的方法来处理用C malloc
创建的导出缓冲区。
所以,这是一个非常愚蠢的c代码,可以解释我在寻找什么。
#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);
}
我编译它: gcc -shared -o playing_ctypes.so playing_ctypes.c
然后我用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
用于知道c_numero
是一个整数,当从python终端调用时,它返回c_long(54)
同时c_numero_2
是动态分配的缓冲区,当它被调用时,它返回c_void_p(147438576)
或c_long(147438576)
它取决于声明的ctypes导出类型。
当我调用testlib.ciao()
时一切正常,但如果我想增加,减少或只是随意改变其中一个ctypes整数的值,我可以用这种方式覆盖它:
c_numero.value = 89
正如我们看到整数一样,它的效果非常好。但对于malloched变量c_number_2
,属性.value
返回缓冲区(?)的地址,如果我想更改其中的整数值,该怎么办呢?
或者,在其他世界中,如何使用ctypes导出指针并以优雅的方式播放其内容值。
可能我会使用memcpy
或写一种python.ctypes处理程序但是,首先写一些丑陋的硬编码,我得请你帮忙。
有吗? :)
答案 0 :(得分: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的重定义进行欺骗以跳过强制转换:
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
答案 1 :(得分:0)
好吧,似乎在三行代码中我可以做到这一点
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
这就是全部:) 欢呼声
答案 2 :(得分:0)
这绝对是最优雅的方式:
c_numero_2_content = (ctypes.c_long).from_address(c_numero_2.value)