ctypes:提取C库返回的结构的成员

发布于 2021-01-29 16:43:41

我正在尝试使用ctypes提取由C库初始化的结构(请参阅例如:https :
//tentacles666.wordpress.com/2012/01/21/python-ctypes-dereferencing-a-
pointer-to-ac
) 。

“原型”是:

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.ax.b

[另请参见使用ctypes从Python中C函数返回的结构访问数据,这无处可寻]

关注者
0
被浏览
173
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    主要是您需要c_void_pvoid *,并且必须使用取消引用返回值.contents

    这是一个工作示例(Windows)…

    编辑 :我添加了一个铸造空指针成员的示例。

    测试

    #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);
    

    测试

    #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。将该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)
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看