'void *' to 'void (*) (bool)' Ошибки с указателями, компилирующими файлы в c с помощью компилятора c ++ - PullRequest
0 голосов
/ 10 мая 2018

Прежде всего, спасибо всем, кто читает и кому вы можете ответить.

Эта часть кода является частью интерфейса библиотеки графического интерфейса, полностью написанного на языке c.

Но я испытываю желание скомпилировать эти записанные файлы в c, с помощью компилятора ac ++, чтобы иметь возможность интегрироваться в программу, которую я делаю с wxwidgets.

В файлах c у меня есть несколько вызовов функций, которыеиметь в качестве аргументов указатели на другие функции.

 typedef struct {
      void (*fchd_ptr)(bool);   
      uint16_t xpos;         
      uint16_t ypos;          
        ...
        ...
}BUTTON_t;

void BT_SetHandler(BUTTON_t* ptr, void* fchd_ptr)
{
    if (ptr == NULL)
        return;

    ptr->fchd_ptr =  fchd_ptr;  // OK in C, ERROR In C++
}

Когда я пытаюсь скомпилировать в C ++, я получаю эту ошибку.

ptr-> fkt_ptr = fkt_ptr;
// error: invalid conversion from 'void *' to 'void (*) (bool)' [-fpermissive]

Если я приведу явное приведение.

ptr-> fkt_ptr = (bool *) fkt_ptr;
// error: can not convert 'bool *' to 'void (*) (bool)' in assignment

Любоепомощь, и объяснение, как решить это будет приветствоваться.

Ответы [ 2 ]

0 голосов
/ 10 мая 2018

Если вы измените сигнатуру функции, чтобы она принимала указатель на функцию, которая соответствует типу, ожидаемому ptr->fchd_ptr. Тогда вам не нужно будет использовать приведение для выполнения задания.

Исходя из вашего вопроса, это будет:

void BT_SetHandler(BUTTON_t* ptr, void (*fchd_ptr)(bool))

Однако, если вы не уверены, какой тип для ptr->fchd_ptr, вы можете заставить компилятор выяснить это для вас. Ранее это можно было сделать только с помощью шаблонной функции, и она получала бы тип на основе того, что было передано в вызов функции во время компиляции. Тем не менее, C ++. 11 обеспечивает decltype, что позволяет вам принудительно указывать тип, который вы хотите для параметра функции, вместо того, чтобы компилятор мог определить его из вызывающих функций.

void BT_SetHandler(BUTTON_t* ptr, decltype(ptr->fchd_ptr) fchd_ptr)

Это нормально, если вы собираетесь компилировать свой код с помощью компилятора C ++.

0 голосов
/ 10 мая 2018

Ваше явное приведение неверно. Вы приводите к bool * (указатель на объект типа bool), когда вам действительно нужно привести к void (*)(bool) (указатель на функцию принимает bool и ничего не возвращает). 1

Если вы замените эту строку на

ptr->fchd_ptr = (void (*)(bool)) fchd_ptr;

он будет компилироваться как в C, так и в C ++.


Однако, если это возможно, вам следует попытаться скомпилировать ваш код на C только на C - хотя мы могли бы заставить эту единственную вещь работать, эти два языка не всегда полностью совместимы, и вы можете столкнуться с проблемами в будущем. Как правило, код C можно компилировать отдельно от частей C ++. Если вы используете extern "C" в заголовочных файлах, вы можете просто связать объекты C ++ и объекты C вместе или оставить часть C в отдельной библиотеке (статической или динамической).

Кроме того, я бы порекомендовал переработать C API, чтобы он действительно брал указатель на функцию на всем протяжении, если это вообще возможно. Псевдоним через void * уродлив и может привести к некоторым действительно неприятным ошибкам и сбоям, если вы передадите неверный тип указателя.


1 Указатели на функции, как правило, сильно отличаются от указателей на объекты, и это зависит от реализации, разрешено ли вам даже приводить между ними. Здесь вам нужен указатель на функцию, а не указатель на объект (например, bool* будет указателем на объект типа bool), чтобы вы могли вызвать его позже. Вы можете видеть в своем примере кода, что void (*fchd_ptr)(bool) является объявлением переменной, которую вы назначаете, что делает void (*)(bool) ее типом. Если вы находите запись несколько запутанной, cdecl.org - отличный способ справиться с теми запутанными именами массивов, указателей и указателей на функции, которые происходят из C.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...