【问题标题】:How do I directly update a C global function pointer variable with Python ctypes?如何使用 Python ctypes 直接更新 C 全局函数指针变量?
【发布时间】:2020-07-18 22:45:24
【问题描述】:

考虑一下test.c

#include <stdio.h>

const char *x = "one";

void set_x(const char *new_x) {
    x = new_x;
}

void print_x(void) {
    printf("x is %s\n", x);
}

void first_f(void) {
    puts("In first function");
}

void (*f)(void) = first_f;

void set_f(void (*new_f)(void)) {
    f = new_f;
}

void do_f(void) {
    f();
}

还有这个test.py

#!/usr/bin/env python3
import ctypes

def second_f():
    print('In second function')

def third_f():
    print('In third function')

test_so = ctypes.CDLL('./test.so')
x_type = ctypes.c_char_p
f_type = ctypes.CFUNCTYPE(None)

test_so.set_x.restype = None
test_so.set_x.argtypes = (x_type,)
test_so.print_x.restype = None
test_so.print_x.argtypes = ()

test_so.set_f.restype = None
test_so.set_f.argtypes = (f_type,)
test_so.do_f.restype = None
test_so.do_f.argtypes = ()

test_so.print_x()
x = x_type.in_dll(test_so, 'x')
x.value = b'two'
test_so.print_x()
new_x = x_type(b'three')
test_so.set_x(new_x)
test_so.print_x()

test_so.do_f()
f = f_type.in_dll(test_so, 'f')
f.value = second_f
test_so.do_f()
new_f = f_type(third_f)
test_so.set_f(new_f)
test_so.do_f()

当我运行 gcc -g -fPIC -shared test.c -o test.so &amp;&amp; ./test.py 时,我会得到以下输出:

x is one
x is two
x is three
In first function
In first function
In third function

我想要/期望得到In second function,而不是第二次出现In first function。为什么不直接使用in_dll 设置全局变量f,而我所做的一切都与x 一样?显然,Python 知道如何将自己的函数转换为 C 函数指针,因为当我使用 third_f 调用 setter 时它可以正常工作。但是如何在没有 setter 的情况下使其工作,例如 x 工作?

【问题讨论】:

  • CFUNCTYPE 创建函数类型,而不是函数指针类型。如果你创建一个函数指针类型并通过正确的类型访问f会发生什么?
  • (另外,您需要保留对通过 f_type 创建的对象的引用,因为 ctypes 无法为您做到这一点。您通过在其生命周期后尝试使用回调来调用未定义的行为结束。)
  • @user2357112supportsMonica 你的意思是如果我不是f_type = ctypes.CFUNCTYPE(None),而是f_type = ctypes.POINTER(ctypes.CFUNCTYPE(None))?然后倒数第二行不变,但最后一行替换为Traceback (most recent call last): File "./test.py", line 33, in &lt;module&gt; test_so.set_f(f_type(third_f)) TypeError: expected CFunctionType instead of function
  • 我更新了我的代码以保留参考。
  • @user2357112supportsMonica A POINTER(CFUNCTYPE(None) 也不起作用。 CFUNCTYPE(NONE) 实例“衰减”为指向函数的指针,因此它更像是指向函数的双指针。我在this answer 中玩过这个问题(这个问题可以标记为那个问题的副本),它也不起作用。 ctypes 似乎不直接支持全局函数指针,必须使用辅助函数。

标签: python c global-variables function-pointers ctypes


【解决方案1】:

与获取x返回的对象不同,以下不支持.value属性,所以没有效果:

f = f_type.in_dll(test_so, 'f')
f.value = second_f 

ctypes 似乎不支持设置全局函数。

【讨论】:

    猜你喜欢
    • 2020-02-13
    • 2013-02-16
    • 2020-09-09
    • 2014-01-27
    • 1970-01-01
    • 2020-04-22
    • 1970-01-01
    • 1970-01-01
    • 2021-11-11
    相关资源
    最近更新 更多