c - 我可以动态转换函数参数吗?
问题描述
我想使用 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 指针的函数,我将传入0
参数is_par_array
,或者1
如果我传递了一个强制转换为的粒子数组空指针,这在c中是否允许?
解决方案
不,您不能可靠地使用void*
来保存函数指针。void*
是通用对象指针类型。
更重要的是,从程序设计的角度来看,将相同的指针/参数用于完全不相关的目的是没有意义的。解决这个问题的正确方法是退后一步,重新思考程序设计。
一些设计思想:
您可以使用 avoid*
指向任何结构,进而包含任何类型,所以这是一个明显的解决方案。此外,由于您使用相同的函数格式,因此可以将函数作为决定函数的参数传递。也就是说,传递一个函数指针以用作“回调”。一般来说,使用全局变量是不好的,所以如果我们可以设计掉它,那就更好了。
我完全不知道实际程序做了什么,但这里有一个使用 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*
.
推荐阅读
- list - OCaml 附加两个列表
- c# - MagickNET - 比较两张图片并仅显示差异,其余透明
- amazon-web-services - 将文件列表从 s3 存储桶复制到另一个
- python - 更改标签大小 - 足球场
- .net - dotnet-dump 不在 macOS 上创建文件
- javascript - 引导折叠/展开具有不同折叠状态的多个目标
- angular - angular - 如何翻译用户输入的文本(在开发过程中未指定)
- javascript - 应打印从键盘输入的文本的自定义事件
- vue.js - Vue CLI:只为异步 Web 组件捆绑公共依赖项一次
- jquery - 数据表在行中隐藏/显示类