ctypes:提取 C 库返回的结构成员
ctypes: extract members of structure returned by C library
我正在尝试使用 ctypes 提取由 C 库初始化的结构(参见示例:https://tentacles666.wordpress.com/2012/01/21/python-ctypes-dereferencing-a-pointer-to-a-c)。
'prototype'是:
mytype * createMyType();
C 中的结构是:
typedef struct
{
int a;
void *b;
}mytype;
来自 python(3)!我这样创建了一个 ctypes 结构:
class mytype(ctypes.Structure):
_fields_ = [("a", ctypes.c_int),
("b", ctypes.POINTER(None))]
C 调用是:
mytype*myinstance = createMyType()
Python调用如下:
import ctypes
f=mylib.createMyType
f.argtypes=()
f.restype=(ctypes.POINTER(mytype),)
x=f()
问题是x
似乎是一个整数;我如何将其解释为指针,或者 - 根据需要 - 提取 x
本身的成员?
如何访问并修改 x.a
和 x.b
?
[另见 Accessing data from a structure returned by C function in Python using ctypes,无处可去]
主要是你需要 c_void_p
作为 void* 并且必须用 .contents
.
取消引用 return
这是一个工作示例 (Windows)...
编辑: 我添加了一个强制转换 void 指针成员的示例。
test.h
#ifdef EXPORT
#define API __declspec(dllexport)
#else
#define API __declspec(dllimport)
#endif
typedef struct
{
int a;
void* b;
} mytype;
API mytype* createMyType();
API void destroyMyType(mytype* p);
test.c
#define EXPORT
#include <stdlib.h>
#include <stdio.h>
#include "test.h"
API mytype* createMyType()
{
int* tmp;
mytype* p = malloc(sizeof(mytype));
p->a = 5;
tmp = malloc(sizeof(int));
*tmp = 123;
p->b = tmp;
printf("%d %p\n",p->a,p->b);
return p;
}
API void destroyMyType(mytype* p)
{
free(p->b);
free(p);
}
test.py
from ctypes import *
class mytype(Structure):
_fields_ = [('a',c_int),
('b',c_void_p)]
test = CDLL('test')
createMyType = test.createMyType
createMyType.argtypes = None
createMyType.restype = POINTER(mytype)
destroyMyType = test.destroyMyType
destroyMyType.argtypes = POINTER(mytype),
destroyMyType.restype = None
t = createMyType()
print('t is',t)
print('t.a is',t.contents.a)
print('t.b is',hex(t.contents.b))
b = cast(t.contents.b,POINTER(c_int))
print('*b is',b.contents)
destroyMyType(t)
输出:注意C代码中输出的void*b地址与t.contents.b
编辑的整数return匹配。 cast
将该整数转换为可以提取内容的 POINTER(c_int)
。
5 00000216C0E2A5D0
t is <__main__.LP_mytype object at 0x00000216C30C4A48>
t.a is 5
t.b is 0x216c0e2a5d0
*b is c_long(123)
我正在尝试使用 ctypes 提取由 C 库初始化的结构(参见示例:https://tentacles666.wordpress.com/2012/01/21/python-ctypes-dereferencing-a-pointer-to-a-c)。
'prototype'是:
mytype * createMyType();
C 中的结构是:
typedef struct
{
int a;
void *b;
}mytype;
来自 python(3)!我这样创建了一个 ctypes 结构:
class mytype(ctypes.Structure):
_fields_ = [("a", ctypes.c_int),
("b", ctypes.POINTER(None))]
C 调用是:
mytype*myinstance = createMyType()
Python调用如下:
import ctypes
f=mylib.createMyType
f.argtypes=()
f.restype=(ctypes.POINTER(mytype),)
x=f()
问题是x
似乎是一个整数;我如何将其解释为指针,或者 - 根据需要 - 提取 x
本身的成员?
如何访问并修改 x.a
和 x.b
?
[另见 Accessing data from a structure returned by C function in Python using ctypes,无处可去]
主要是你需要 c_void_p
作为 void* 并且必须用 .contents
.
这是一个工作示例 (Windows)...
编辑: 我添加了一个强制转换 void 指针成员的示例。
test.h
#ifdef EXPORT
#define API __declspec(dllexport)
#else
#define API __declspec(dllimport)
#endif
typedef struct
{
int a;
void* b;
} mytype;
API mytype* createMyType();
API void destroyMyType(mytype* p);
test.c
#define EXPORT
#include <stdlib.h>
#include <stdio.h>
#include "test.h"
API mytype* createMyType()
{
int* tmp;
mytype* p = malloc(sizeof(mytype));
p->a = 5;
tmp = malloc(sizeof(int));
*tmp = 123;
p->b = tmp;
printf("%d %p\n",p->a,p->b);
return p;
}
API void destroyMyType(mytype* p)
{
free(p->b);
free(p);
}
test.py
from ctypes import *
class mytype(Structure):
_fields_ = [('a',c_int),
('b',c_void_p)]
test = CDLL('test')
createMyType = test.createMyType
createMyType.argtypes = None
createMyType.restype = POINTER(mytype)
destroyMyType = test.destroyMyType
destroyMyType.argtypes = POINTER(mytype),
destroyMyType.restype = None
t = createMyType()
print('t is',t)
print('t.a is',t.contents.a)
print('t.b is',hex(t.contents.b))
b = cast(t.contents.b,POINTER(c_int))
print('*b is',b.contents)
destroyMyType(t)
输出:注意C代码中输出的void*b地址与t.contents.b
编辑的整数return匹配。 cast
将该整数转换为可以提取内容的 POINTER(c_int)
。
5 00000216C0E2A5D0
t is <__main__.LP_mytype object at 0x00000216C30C4A48>
t.a is 5
t.b is 0x216c0e2a5d0
*b is c_long(123)