【问题标题】:ctypes: get the actual address of a c functionctypes:获取一个c函数的实际地址
【发布时间】:2018-04-03 16:38:40
【问题描述】:

这很棘手(至少对我来说 :-),也许不可行。但我试着问你。

我有这个 c 共享库:

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

static int variable = -666;

int get_value() {
    return variable;
}

void print_pointer_to_get_value() {
    printf("pointer_to_get_value: %p\n", &get_value);
}

以这种方式编译(在 Linux 上):

gcc -fPIC -c -O2 shared.c && gcc -shared -o shared.so shared.o

现在我加载库并调用 print_pointer_to_get_value():

>>> import ctypes
>>> so = ctypes.cdll.LoadLibrary('./shared.so')
>>> so.print_pointer_to_get_value()
pointer_to_get_value: 0x7f46e178f700

我想从 ctypes 中获取由 print_pointer_to_get_value() 打印的 get_value 函数的实际地址(整数形式)。 我的最终目标是将该地址移动到 Cython 模块并在“nogil”Cython 函数中调用该函数。我需要在运行时加载 .so 库,因此我无法编译将其链接到库的 Cython 模块。

谢谢 1000。

【问题讨论】:

    标签: python cython ctypes


    【解决方案1】:

    这是一个令人讨厌的多步骤过程,不容易优雅地完成:

    一些 Cython 代码:

    ctypedef double (*math_function_t)(double) nogil
    
    import ctypes
    
    def call_f(f, double x):
        cdef math_function_t cy_f_ptr = (<math_function_t*><size_t>ctypes.addressof(f))[0]
    
        cdef double res
        with nogil:
            res = cy_f_ptr(x)
        return res
    

    在这里,我向 Cython 传递了一个 Ctypes 函数类型 (f) 并在 Cython 中获取地址。我认为不可能在 Python 中获取地址。作为如何初始化 f 的示例,在 Linux 上您可以这样做:

    lib = ctypes.cdll.LoadLibrary("libm.so.6")
    f = lib.sin
    
    call_f(f,0.5) # returns sin(0.5)
    

    (使用标准库sin函数)。

    Cython 行 cdef math_function_t cy_f_ptr = (&lt;math_function_t*&gt;&lt;size_t&gt;ctypes.addressof(f))[0] 可以分解如下:

    1. ctypes.addressof(f) 获取 ctypes 变量 f 所在的地址。__这不是您所追求的值_ - 它是您所追求的值的存储位置。
    2. 首先将其转换为size_t 整数,然后转换为指向cdef 函数指针类型的指针。 Cython 需要两步转换。
    3. [0] 取消引用您的 math_function_t* 以获得 math_function_t。这是函数指针(即你想要的值)

    此答案的信息来自this newsgroup thread(我目前无法访问)

    【讨论】:

    • 太完美了!你甚至告诉我为什么ctypes.addressof() 给出了不同的指针。还有一个问题:为什么&lt;size_t&gt;?我不是在问这个演员的必要性,而是为什么 size_t 而不是其他类型。
    • 它需要足够大的 int 来容纳指针。实际上 size_t 会这样做(尽管不能保证......)。虽然我认为uintptr_t 实际上是正确的使用方式
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-25
    • 2019-01-26
    • 2020-12-03
    相关资源
    最近更新 更多