c++ - 如何成功地将功能对象(或 lambda)传递给轨迹栏回调第二个参数(void*)?
问题描述
我的班级有一个成员函数:
void handler(int pos, cv::Mat &image)
{
threshold(image, image, pos, 255, CV_THRESH_BINARY);
cv::imshow("window", this->image); //<-- segfault
}
并且有一个 createTrackbar 的成员回调函数:
static void on_trackbar(int pos, void* ptr);
然后我在另一个成员函数中创建这个函数对象:
std::function<void(int)> bind_handler = std::bind(static_cast<void (my_class::*)(int, cv::Mat&)>(&my_class::handler), this, std::placeholders::_1, img_threshold);
slider = 0;
cv::namedWindow("Test Filter", 1);
cv::createTrackbar("threshold", "Test Filter", &slider, 255, on_trackbar, (void*)&bind_handler);
然后在on_trackbar我抓住了void* ptr:
std::function<void(int)>* cb = static_cast<std::function<void(int)>* >(ptr);
(*cb)(pos); //<-- segfault
编译好。
但是当我触摸滑块时,它会出现分段错误:(
我也用 lambdas尝试了这段代码,但它也有段错误。
如果我std::shared_ptr<cv::Mat> thrsh_ptr
通过[=]处理lambda,它也会出现段错误。
如何正确制作?
UPD:在处理程序主体中调用。我发现成员函数被回调调用cv::Mat image
后,成员变为0x0 。我在正文之前和内部检查它的地址;在这两种情况下,它都是相同的地址值。handler
on_trackbar
cv::createTrackbar
handler
解决方案
正如评论中提到的,bind_handler
是一个局部变量,在创建跟踪栏后立即不复存在。当库尝试调用回调时,它会进入您的on_trackbar()
函数,传递一个指向现已失效的std::function<>
对象的指针,这会在您尝试取消引用它时导致崩溃。该void* ptr
参数指向一个不再存在的先前局部变量。
正如@nm 所提到的,您需要做的是将指针传递给包含cv::Mat
. 在内部bind_handler()
,您将void*
参数转换回您的对象类型,并从那里访问图像,调用您希望的任何成员函数。您的问题不够明确,我无法理解您的完整设计,但是是这样的:
class MyClass {
cv::Mat img_threshold;
void handler(int pos) {
cv::threshold(img_threshold, img_threshold, pos, 255, CV_THRESH_BINARY);
cv::imshow("window", img_threshold);
}
public:
static void on_trackbar(int pos, void* ptr) {
MyClass* obj = reinterpret_cast<MyClass*>(ptr);
obj->handler(pos);
}
void other_function() {
slider = 0;
cv::namedWindow("Test Filter", 1);
cv::createTrackbar("threshold", "Test Filter", &slider, 255, on_trackbar, static_cast<void*>(this));
}
};
推荐阅读
- linux - 具有延迟线程的多线程应用程序的 stdout/stderr 的 QProcess 输出
- search - 在大文件中搜索特殊字符
- javascript - JS ES6 如何通过自己的模板对数组进行排序?
- c - 临时指针:正确的 malloc 和 free
- javascript - 保证将 AWS Lambda 函数限制在指定的预算范围内
- angular - 在 Nativescript Angular 中向数组添加值时出现未定义的错误
- javascript - scala.js 的字符串插值,如 java.text.MessageFormat
- azure - Azure SSIS 中的 C# 脚本源 Microsoft.Sharepoint.Client 程序集
- java - Liquibase maven 插件 - 设置日志记录级别
- javascript - cytoscape.js 的径向树布局?