【发布时间】:2026-01-09 12:15:01
【问题描述】:
我在理解如何将 this 传递给传递给库的回调函数时遇到了一些麻烦。该函数需要有一个特定的签名。
有问题的库是 OCILIB (https://vrogier.github.io/ocilib/doc/html/classocilib_1_1_subscription.html) 并尝试将类函数作为 Register() 的第四个参数传递。
我可以按如下方式顺利通过
&database::callback // a static function of database
或
[](ocilib::Event &event) // as lambda function
{
}
但它无权访问实例变量。我试着像这样使用它
[&](ocilib::Event &event) // as lambda function
{
}
但签名不匹配,我收到以下错误
database.cpp: In member function ‘bool dcn::database::watch(std::__cxx11::string)’:
database.cpp:104:44: error: no matching function for call to ‘ocilib::Subscription::Register(ocilib::Connection&, std::__cxx11::string&, ocilib::Subscription::ChangeTypesValues, dcn::database::watch(std::__cxx11::string)::<lambda(ocilib::Event&)>, unsigned int, unsigned int)’
}, (unsigned int) 7778, (unsigned int) 0);
^
In file included from /usr/include/ocilib.hpp:9194:0,
from /home/ai/dcn/include/main.h:17,
from database.cpp:1:
/usr/include/ocilib_impl.hpp:6650:13: note: candidate: void ocilib::Subscription::Register(const ocilib::Connection&, const ostring&, ocilib::Subscription::ChangeTypes, ocilib::Subscription::NotifyHandlerProc, unsigned int, unsigned int)
inline void Subscription::Register(const Connection &connection, const ostring& name, ChangeTypes changeTypes, NotifyHandlerProc handler, unsigned int port, unsigned int timeout)
^~~~~~~~~~~~
/usr/include/ocilib_impl.hpp:6650:13: note: no known conversion for argument 4 from ‘dcn::database::watch(std::__cxx11::string)::<lambda(ocilib::Event&)>’ to ‘ocilib::Subscription::NotifyHandlerProc {aka void (*)(ocilib::Event&)}’
make[1]: *** [database.o] Error 1
函数定义为
static void callback(ocilib::Event &);
需要您的帮助来解决这个问题。提前致谢。
【问题讨论】:
-
是的 - 经典问题。 OCILIB 仅允许您为回调注册
void (*)(ocilib::Event&),并且只能与静态成员或独立函数匹配。您需要编写这样一个函数,该函数在内部查阅一些记录以计算出调用成员函数的事件。例如,它可能会在回调期间查看ocilib::Event参数内部,然后使用一些 id 查找关联容器(map、unordered_map)以找到指向对象的指针以调用非静态成员函数开。 -
(如果 OCILIB 的
Subscription::Register用现代 C++ 重写,它应该更改为std::function参数而不是非成员函数指针参数,这将允许您通过 lambdas捕获。) -
如果 API 没有为您提供通过
void*的选项,那么如果不求助于不太理想的解决方案,您将无能为力。你能提供一些关于这个电话的背景信息吗?进行调用的代码可以在同一个程序执行中多次运行吗? -
@chris 是的,它会被调用很多次。回调是钩子的一部分,它将等待数据库中的更改并复制到不同的数据库。
-
我不是指回调本身,而是注册回调的代码。有不同级别的hacky解决方案,一种是生成一个函数指针,如果再次调用注册码,该函数指针将被覆盖。其他级别是不同程度的更多工作,涵盖更少或更弱的假设。
标签: c++