通过Ctypes从C到Python-将函数指针的结构包装为静态函数

发布于 2021-01-29 14:59:57

我在C库中有这样的结构。DataFn中的函数指针指向静态函数。

。H

struct Data {
    int i;
    int *array;
};

typedef struct {
    bool (* const fn1) (struct Data*, const char *source);
    ....
} DataFn;
extern DataFn const DATAFUNC

使用objdump,该表仅包含DATAFUNC和gcc的其他内容。

这在C语言中很好,在其中调用fn1就像DATAFUNC.fn1(…,…),但是这样的东西如何包装起来,以便可以在python w /
ctypes中调用fn1呢?

python示例

libc = ctypes.cdll.LoadLibrary("./data.so")
print(libc.DATAFUNC)

结果是 <_FuncPtr object at 0x6ffffcd7430>

这是相似的,但是没有工厂功能。

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

    [Python 3.Docs]:ctypes-
    Python的外部函数库
    包含解决此问题所需的一切。

    我相信缺少的主要部分是 ctypes 类型的 in_dll 方法( 访问从dll* 部分 导出的值 )。 __ *

    除此之外,为了使用 C 数据,您需要让 Python 知道数据格式。这适用于:

    • 结构 s。通过子类定义 Python 副本ctypes.Structure
    • 函数指针(适用于您的情况)。使用定义它们ctypes.CFUNCTYPE

    我准备了一个简化的示例来说明上述内容。请注意,为了简化操作,我没有进行任何错误处理(检查 NULL应该是 ))。

    ch

    struct Data {
        int i;
    };
    
    
    typedef struct {
        int (* const fn1) (struct Data*, const char*);
    } DataFn;
    
    
    extern DataFn const DATAFUNC;
    

    抄送

    #include <stdio.h>
    #include "c.h"
    
    
    static int func1(struct Data *pData, const char *source) {
        printf("From C - Data.i: [%d], source: [%s]\n", pData->i, source);
        return -255;
    }
    
    
    DataFn const DATAFUNC = {&func1};
    

    code00.py

    #!/usr/bin/env python3
    
    
    import sys
    from ctypes import c_int, c_char_p, Structure, CDLL, CFUNCTYPE, POINTER, byref
    
    
    class Data(Structure):
        _fields_ = [
            ("i", c_int),
        ]
    
    
    fn1_type = CFUNCTYPE(c_int, POINTER(Data), c_char_p)
    
    
    class DataFn(Structure):
        _fields_ = [
            ("fn1", fn1_type),
        ]
    
    
    def main():
        data = Data(127)
        dll = CDLL("./c.so")
        data_func = DataFn.in_dll(dll, "DATAFUNC")
        ret = data_func.fn1(byref(data), "abcd".encode())
        print("DATAFUNC.fn1 returned {:d}".format(ret))
    
    
    if __name__ == "__main__":
        print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
        main()
    

    输出

    [cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q049962265]> ls
    c.c  c.h  code00.py
    [cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q049962265]> gcc
    

    -shared -fPIC -o c.so c.c
    [cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q049962265]> ls
    c.c c.h code.py c.so
    [cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q049962265]> objdump
    -t c.so | grep DATAFUNC
    0000000000200e10 g O .data.rel.ro 0000000000000008
    DATAFUNC
    [cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q049962265]> python3
    code00.py
    Python 3.5.2 (default, Nov 23 2017, 16:37:01)
    [GCC 5.4.0 20160609] on linux

    From C - Data.i: [127], source: [abcd]
    DATAFUNC.fn1 returned -255
    


知识点
面圈网VIP题库

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

去下载看看