У меня есть два типа указателей на функции, определенные в моем C ++, которые выглядят так:
typedef void(*CallbackFn)(bool, std::string, py::array_t<uint8_t>&);
typedef std::function<void(std::string)> LogFunction;
Class Core{
...
void myfunc1(LogFunction lg1, CallbackFn callback, int x, std::string y);
};
, и я хочу иметь возможность выставить их в C, но я не могу найти способ сделать это. Моя первая попытка состояла в том, чтобы привести их как void*
, а затем вернуть их обратно к их фактическому типу. но это кажется плохой идеей. Так что я не знаю, как go узнать об этом преобразовании.
Также решение, которое мне нужно найти, должно быть выполнимо, по крайней мере, на C ++ 11.
Обновление:
Большое спасибо за ваши ответы. Тем не менее мне нужно добавить немного больше объяснений, как то, что я после. Я знаю о extern "C"
, и на самом деле функции C++
представлены с использованием этого уже в моем DLL
. Однако проблема, с которой я столкнулся, состояла в том, чтобы передать указатели на функции туда и обратно между C и C ++.
Один из способов состоял в том, чтобы определить указатели на функции так, чтобы они могли быть непосредственно использованы C. То есть мне нужно было изменить, например:
typedef void(*CallbackFn)(bool, std::string, py::array_t<uint8_t>&);
typedef std::function<void(std::string)> LogFunction;
на C совместимый:
typedef void(*CCallbackFn)(bool, char*, int, unsigned char, int length);
typedef void(*CLogFunction)(char* string, int length);
и использовать их вместо этого. Тем не менее, недостатком этого является то, что DLL также используется клиентами C ++, и это будет помехой для того, чтобы все C ++ было совместимо с C, и я потерял бы преимущества C ++, делая это.
Вместо этого я решил придумать второй путь. C ++ остается прежним, но для связи C и взаимодействия с другими языками через C API я выполняю преобразование самостоятельно.
То есть они используют стиль C, а затем я преобразую это обратно в C ++ в часть реализации. Чтобы еще больше упростить это, я разработал некоторые настройки по умолчанию для части C ++. То есть, предположим, из-за отсутствия лучшего примера, экземпляру нужна функция обратного вызова, чтобы регистрировать все, что происходит. Я определяю функцию обратного вызова в случае, если она не была предоставлена пользователем, и создаю две функции для C API, в частности что-то примерно похожее на это:
//in core.cpp for example
include "Core.h"
...
extern "C"
{
Core * core;
...
Core_API void* get_default_log_callback()
{
return (void*) core->SomeDefaultCallback();
}
Core_API void* set_log_callback(void* fn)
{
// convert/cast that to the c++ callback type
// CallbackFn,
core->SetCallback(fn_converted);
}
, и клиент может, например, использовать get_default_log_callback и использовать его возвращение к set_log_call_back
. По сути, идея заключается в том, чтобы использовать уже определенные ресурсы C ++. Я застрял в этом процессе преобразования, как преобразовать такие указатели обратного вызова в C совместимый тип (например, как я показал, было бы очень просто просто привести указатель к void *, например, и написать оболочку C который принимает void * и затем преобразовывает его в правильный тип.
Я хотел бы также знать об этом сценарии и о том, является ли это хорошей практикой или иным образом плохой.
Второй вопрос:
Также я хотел бы знать, возможно ли преобразование, например, из CCallbackFn
и CallbackFn
?
Предположим, у меня есть функция (мой * 1053). * функция выше, например) в форме CCalbackFn
, но в конечном итоге я хочу получить ее в форме CallbackFn
(изменить ее и вызвать базовый C ++, который принимает CallbackFn
)? это возможно?