Я не могу поверить, что это работает, или у вас есть довольно узкое определение «это работает» (например, вы нашли одну конкретную установку, где, кажется, она делает то, что, как вы думаете, должна делать). Мне не ясно, что делает dispatch_sync_f()
, но я думаю, что это подозрительно, что он получает указатель на локальную переменную context
в качестве параметра. Предполагая, что эта переменная переживает использование этого указателя, по-прежнему существует тонкая проблема, которая не поможет вам на большинстве платформ, но на некоторых:
Соглашения о вызовах C и C ++ могут отличаться. То есть вы не можете привести указатель на функцию C ++ к указателю на функцию C и надеяться, что это будет вызвано. Решение этой проблемы - и ваш первоначальный вопрос - это, конечно, дополнительный уровень косвенности: не отправляйте функцию, которую вы получаете в качестве аргумента, а скорее отправляйте ее функции C (т.е. функции C ++, объявленной как extern "C"
), который берет свой собственный контекст, содержащий как исходный контекст, так и исходную функцию, и вызывает исходную функцию. Единственное необходимое явное приведение - это static_cast<>()
, восстанавливающий указатель на ваш внутренний контекст из void*
.
Поскольку вы, кажется, реализуете шаблон, вам может потребоваться использовать другое косвенное обращение, чтобы избавиться от этого типа: я не думаю, что шаблоны функций могут быть объявлены extern "C"
. Так что вам нужно как-то восстановить исходный тип, например, используя базовый класс и виртуальную функцию или что-то вроде std::function<void()>
, содержащее легко вызываемый функциональный объект, выполняющий это преобразование (указатель на этот объект будет вашим контекстом).