Могу ли я динамически приводить аргумент функции?

#c #function-pointers #void-pointers

#c #указатели на функции #пустые указатели

Вопрос:

Я хочу реализовать алгоритм маршевых кубов с использованием c. Этот алгоритм создает поверхность из объема. Иногда функция будет получать массив частиц, описывающий объем, а иногда она будет получать функцию скалярного поля (функция, которая получает некоторое местоположение и возвращает некоторое значение). Вместо создания двух отдельных функций я хочу, чтобы функция marching cubes получала указатель 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), где я буду отслеживать себя, я имею в виду, что я передам 0 в is_par_array аргументе, если я передал функцию, приведенную к указателю void, или передам 1 , если я передал массив частиц, приведенный к указателю void, разрешено ли это в c?

Комментарии:

1. Итак, используя простой язык, вы хотели бы передать либо указатель на функцию, либо массив частиц через void * тип аргумента, затем привести этот аргумент к его надлежащему типу в зависимости от того, какое значение is_par_array имеет?

2. @ryyker Да, это то, что я хотел бы сделать.

Ответ №1:

Нет, вы не можете надежно использовать void* для хранения указателей на функции. void* является универсальным типом указателя объекта.

Что еще более важно, с точки зрения разработки программы не имеет смысла использовать один и тот же указатель / параметр для совершенно не связанных целей. Правильный способ решить эту проблему — сделать шаг назад и переосмыслить дизайн программы.

Некоторые дизайнерские соображения:
Вы можете использовать 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 void* .

Комментарии:

1. @ryyker Проще говоря, объекты = переменные. Указатели на объекты = указатели на переменные. Указатели на функции = указатели на функции.

2. Они не являются несвязанными целями. Я хочу использовать тот же алгоритм, но изменить способ, которым алгоритм оценивает некоторое местоположение (внутри или снаружи тома). В любом случае я изменю дизайн программы и создам две отдельные функции, спасибо!