【问题标题】:Can I dynamically cast a function argument?我可以动态转换函数参数吗?
【发布时间】:2020-12-20 14:23:27
【问题描述】:

我想使用 c 实现行进立方体算法。该算法从体积创建表面。有时该函数会接收一个描述体积的粒子数组,有时它会接收一个标量场函数(一个接收某个位置并返回某个值的函数)。我不希望创建两个单独的函数,而是希望行进立方体函数接收一个 void 指针。如果所需的方法是粒子的表面,它将指针转换为粒子数组,否则将其转换为函数指针。这是我想要的插图:

particle_array* global_par_array;
double (*global_scalar_field)(location);

double value_according_to_par_array(location loc){
        //use the global_par_array and return a value
        return value;
}
double value_according_to_scalar_field(location loc){
        //use the global_scalar_field and return a value
        return value;
}
void marching_cubes(mesh* surface ,void* par_array_or_function, char is_par_array){
//                  ^ need this argument to 
//                    be dynamically casted
    double (*method)(location loc);
    if (is_par_array){
        global_par_array = (particle_array*)(*par_array_or_function);
        method = value_according_to_par_array;
    }
    else{
        global_scalar_field = (double(*)(location))(*par_array_or_function);
        method = value_according_to_scalar_field;
    }
    //do the marching cubes algorithm according to method, changing *surface
    return;

我将在 python 中调用此函数(使用 ctypes),我将在其中跟踪自己,我的意思是,如果我传递了一个强制转换为 void 指针的函数,我将在 is_par_array 参数中传递 0,或者通过1 如果我传递了一个强制转换为 void 指针的粒子数组,这在 c 中是否允许?

【问题讨论】:

  • 因此,使用简单的语言,您想通过 void * 参数类型传递函数指针或粒子数组,然后根据 @ 的值将该参数转换为正确的类型987654326@是?
  • @ryyker 是的,这就是我想做的。

标签: c function-pointers void-pointers


【解决方案1】:

不,您不能可靠地使用void* 来保存函数指针。 void* 是通用的 object 指针类型。

更重要的是,从程序设计的角度来看,将相同的指针/参数用于完全不相关的目的是没有意义的。解决这个问题的正确方法是退后一步,重新思考程序设计。

一些设计思路:
可以使用void* 指向任何结构,进而包含任何类型,因此这是一个明显的解决方案。此外,由于您使用相同的函数格式,因此可以将函数作为决定函数的参数传递。也就是说,传递一个函数指针以用作“回调”。一般来说,使用全局变量是不好的,所以如果我们能把它设计掉,那就更好了。

我完全不知道实际的程序做了什么,但这里建议使用 C 中的传统泛型编程进行重新设计:

typedef double march_cube_t (location, void*);


double march_particle_array (location loc, void* data)
{
  // cast data to a struct or object pointer type specific for this function
  ...
  return value;
}

double march_scalar_field (location loc, void* data)
{
  // cast data to a struct or object pointer type specific for this function
  ...
  return value;
}

void marching_cubes(mesh* surface, march_cube_t* algo, void* data)
{
  ...
  double result = algo(some_location, data);
}

在适用的情况下还要考虑 const 正确性。如果你不需要修改数据,那么这些应该是const void*

【讨论】:

  • @ryyker 简单地说,对象 = 变量。对象指针 = 指向变量的指针。函数指针 = 函数指针。
  • 它们不是无关的目的。我想使用相同的算法,但更改算法评估某个位置(在体积内部或外部)的方式。无论如何我会改变程序设计并创建两个单独的功能,谢谢!
猜你喜欢
  • 2020-07-15
  • 2014-01-31
  • 1970-01-01
  • 2012-01-09
  • 2017-07-08
  • 2015-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多