使用 ctypes 回调功能时的访问冲突

问题描述

我正在尝试使用 ctypes 回调功能将 python 函数作为函数指针传递给 C 函数。这是 C:

typedef void(*f1)();

void function_that_takes_a_function(f1* fn){
    printf("I'm a function that takes a function\n");
    double d1[2] = {0.1,0.2} ;
    printf("1\n");
    double *d2;
    printf("2\n");
    double *g;
    printf("3\n");

    printf("%d\n",(long )fn);

    (*fn)(); 
    printf("4\n");
}

还有 Python

        import ctypes as ct

        lib = ct.CDLL("SRES")
        F1_CALLBACK = ct.CFUNCTYPE(None)
        function_that_takes_a_function = lib.function_that_takes_a_function
        function_that_takes_a_function.argtypes = [F1_CALLBACK]
        function_that_takes_a_function.restype = None

        @F1_CALLBACK
        def func_to_pass_in():
            print("hello from Python")

        function_that_takes_a_function(func_to_pass_in)

这给了我

I'm a function that takes a function
1
2
3
-1788276848

Error
Traceback (most recent call last):
  File "C:\Miniconda3\envs\py38\lib\unittest\case.py",line 60,in testPartExecutor
    yield
  File "C:\Miniconda3\envs\py38\lib\unittest\case.py",line 676,in run
    self._callTestMethod(testMethod)
  File "C:\Miniconda3\envs\py38\lib\unittest\case.py",line 633,in _callTestMethod
    method()
  File "Guassianproblem.py",line 77,in testFunctionPointerInIsolation
    function_that_takes_a_function(func_to_pass_in)
OSError: exception: access violation writing 0xFFFFFFFFF9158D4C

我希望看到的地方:

I'm a function that takes a function
1
2
3
Hello from Python 
4

有人能发现我的问题吗?

解决方法

f1 已经是一个指向返回类型为 void 且没有参数的函数的指针(参见类型定义)。 以下作品。

typedef void(*f1)();
    
void function_that_takes_a_function(f1 fn)
{
  fn();
}

使用以下 Python 代码:

        import ctypes as ct

        lib = ct.CDLL("SRES")
        F1_CALLBACK = ct.CFUNCTYPE(None)
        function_that_takes_a_function = lib.function_that_takes_a_function
        function_that_takes_a_function.argtypes = [F1_CALLBACK]
        function_that_takes_a_function.restype = None

        @F1_CALLBACK
        def func_to_pass_in():
            print("hello from Python")

        function_that_takes_a_function(func_to_pass_in)