如何将成员函数传递给 g_source_set_callback?
How do I pass member functions to g_source_set_callback?
我正在尝试将成员函数指针传递给 g_source_set_callback
以将它们排队。这是我写的伪代码。
#include<glib.h>
#include<iostream>
#include<thread>
#include<chrono>
using namespace std;
using namespace std::chrono_literals;
class executor
{
private:
GMainLoop* main_loop;
GMainContext* worker_context;
thread worker_thread;
void worker_loop()
{
g_main_context_push_thread_default(worker_context);
cout << "Starting main loop" << endl;
g_main_loop_run(main_loop);
cout << "Finished main loop" << endl;
g_main_context_pop_thread_default(worker_context);
}
void queue_callback(int (*callback)(void))
{
GSource* idle_source = g_idle_source_new();
g_source_set_callback(idle_source, (GSourceFunc)callback, NULL, NULL);
g_source_attach(idle_source, worker_context);
g_source_unref(idle_source);
}
int func1()
{
cout << "func1 started" << endl;
this_thread::sleep_for(5s);
cout << "func1 finished waiting" << endl;
return 0;
}
int func2()
{
cout << "func2 started" << endl;
this_thread::sleep_for(1s);
cout << "func2 finished waiting" << endl;
return 0;
}
public:
executor()
{
worker_context = g_main_context_new();
main_loop = g_main_loop_new(worker_context, false);
worker_thread = thread(&executor::worker_loop, this);
}
~executor()
{
cout << "Stopping main loop" << endl;
GSource* idle_source = g_idle_source_new();
g_source_set_callback(idle_source, (GSourceFunc)g_main_loop_quit, main_loop, NULL);
g_source_attach(idle_source, worker_context);
g_source_unref(idle_source);
if (worker_thread.joinable())
{
worker_thread.join();
}
cout << "Removing references to main loop and context" << endl;
g_main_loop_unref(main_loop);
g_main_context_unref(worker_context);
}
void start()
{
queue_callback(func1);
queue_callback(func2);
}
};
int main()
{
executor e;
e.start();
return 0;
}
我知道你不能像那样传递非静态成员函数,所以,我得到了预期的编译错误。
test.cpp: In member function ‘void executor::start()’:
test.cpp:79:37: error: invalid use of non-static member function ‘int executor::func1()’
queue_callback(func1);
^
test.cpp:35:13: note: declared here
int func1()
^~~~~
test.cpp:80:37: error: invalid use of non-static member function ‘int executor::func2()’
queue_callback(func2);
^
test.cpp:43:13: note: declared here
int func2()
^~~~~
我看到有人用函数对象来包装成员函数。所以,我尝试了这个。
#include<glib.h>
#include<iostream>
#include<thread>
#include<chrono>
#include<functional>
using namespace std;
using namespace std::chrono_literals;
class executor
{
private:
GMainLoop* main_loop;
GMainContext* worker_context;
thread worker_thread;
void worker_loop()
{
g_main_context_push_thread_default(worker_context);
cout << "Starting main loop" << endl;
g_main_loop_run(main_loop);
cout << "Finished main loop" << endl;
g_main_context_pop_thread_default(worker_context);
}
void queue_callback(const function<int()>* callback)
{
GSource* idle_source = g_idle_source_new();
g_source_set_callback(idle_source, reinterpret_cast<GSourceFunc>(&on_callback), const_cast<function<int()>*>(callback), NULL);
g_source_attach(idle_source, worker_context);
g_source_unref(idle_source);
}
static int on_callback(const function<int()>* callback)
{
return (*callback)();
}
int func1()
{
cout << "func1 started" << endl;
this_thread::sleep_for(5s);
cout << "func1 finished waiting" << endl;
return 0;
}
int func2()
{
cout << "func2 started" << endl;
this_thread::sleep_for(1s);
cout << "func2 finished waiting" << endl;
return 0;
}
public:
executor()
{
worker_context = g_main_context_new();
main_loop = g_main_loop_new(worker_context, false);
worker_thread = thread(&executor::worker_loop, this);
}
~executor()
{
cout << "Stopping main loop" << endl;
GSource* idle_source = g_idle_source_new();
g_source_set_callback(idle_source, (GSourceFunc)g_main_loop_quit, main_loop, NULL);
g_source_attach(idle_source, worker_context);
g_source_unref(idle_source);
if (worker_thread.joinable())
{
worker_thread.join();
}
cout << "Removing references to main loop and context" << endl;
g_main_loop_unref(main_loop);
g_main_context_unref(worker_context);
}
void start()
{
cout << "Submitting func1 callback" << endl;
function<int()> callback1 = [this]() {
return func1();
};
queue_callback(&callback1);
cout << "Submitting func2 callback" << endl;
function<int()> callback2 = [this]() {
return func2();
};
queue_callback(&callback2);
}
};
int main()
{
executor e;
e.start();
return 0;
}
这段代码可以编译,但我总是遇到分段错误或 bad_function_call 异常。
Starting main loop
Submitting func1 callback
Submitting func2 callback
Stopping main loop
func1 started
func1 finished waiting
terminate called after throwing an instance of 'std::bad_function_call'
what(): bad_function_call
Aborted (core dumped)
我想我收到了错误,因为 callback1
和 callback2
是本地对象,当它们被执行时,它们的内存已被释放。
我该如何解决这个问题?我想过使用 unique_ptr
s,但无法弄清楚 g_source_set_callback
如何将 int (*GSourceFunc) void
作为第二个参数,将 void*
作为第三个参数。
我明白了。
我创建了一个新的 std::function
对象并将其传递给 g_source_set_callback
。当调用 on_callback
时,我将 void *
类型转换为 std::function<int()>*
,调用它并删除它。
这是工作代码。
#include<glib.h>
#include<iostream>
#include<thread>
#include<chrono>
#include<functional>
using namespace std;
using namespace std::chrono_literals;
class executor
{
private:
GMainLoop* main_loop;
GMainContext* worker_context;
thread worker_thread;
void worker_loop()
{
g_main_context_push_thread_default(worker_context);
cout << "Starting main loop" << endl;
g_main_loop_run(main_loop);
cout << "Finished main loop" << endl;
g_main_context_pop_thread_default(worker_context);
}
void queue_callback(function<int()>&& callback)
{
GSource* idle_source = g_idle_source_new();
g_source_set_callback(idle_source, on_callback, new function<int()>(callback), NULL);
g_source_attach(idle_source, worker_context);
g_source_unref(idle_source);
}
static int on_callback(void* ptr)
{
function<int()>* callback = static_cast<function<int()>*>(ptr);
int ret = (*callback)();
delete callback;
return ret;
}
int func1()
{
cout << "func1 started" << endl;
this_thread::sleep_for(5s);
cout << "func1 finished waiting" << endl;
return 0;
}
int func2()
{
cout << "func2 started" << endl;
this_thread::sleep_for(1s);
cout << "func2 finished waiting" << endl;
return 0;
}
public:
executor()
{
worker_context = g_main_context_new();
main_loop = g_main_loop_new(worker_context, false);
worker_thread = thread(&executor::worker_loop, this);
}
~executor()
{
cout << "Stopping main loop" << endl;
GSource* idle_source = g_idle_source_new();
g_source_set_callback(idle_source, (GSourceFunc)g_main_loop_quit, main_loop, NULL);
g_source_attach(idle_source, worker_context);
g_source_unref(idle_source);
if (worker_thread.joinable())
{
worker_thread.join();
}
cout << "Removing references to main loop and context" << endl;
g_main_loop_unref(main_loop);
g_main_context_unref(worker_context);
}
void start()
{
cout << "Submitting func1 callback" << endl;
queue_callback([this]() { return func1(); });
cout << "Submitting func2 callback" << endl;
queue_callback([this]() { return func2(); });
}
};
int main()
{
executor e;
e.start();
return 0;
}
我正在尝试将成员函数指针传递给 g_source_set_callback
以将它们排队。这是我写的伪代码。
#include<glib.h>
#include<iostream>
#include<thread>
#include<chrono>
using namespace std;
using namespace std::chrono_literals;
class executor
{
private:
GMainLoop* main_loop;
GMainContext* worker_context;
thread worker_thread;
void worker_loop()
{
g_main_context_push_thread_default(worker_context);
cout << "Starting main loop" << endl;
g_main_loop_run(main_loop);
cout << "Finished main loop" << endl;
g_main_context_pop_thread_default(worker_context);
}
void queue_callback(int (*callback)(void))
{
GSource* idle_source = g_idle_source_new();
g_source_set_callback(idle_source, (GSourceFunc)callback, NULL, NULL);
g_source_attach(idle_source, worker_context);
g_source_unref(idle_source);
}
int func1()
{
cout << "func1 started" << endl;
this_thread::sleep_for(5s);
cout << "func1 finished waiting" << endl;
return 0;
}
int func2()
{
cout << "func2 started" << endl;
this_thread::sleep_for(1s);
cout << "func2 finished waiting" << endl;
return 0;
}
public:
executor()
{
worker_context = g_main_context_new();
main_loop = g_main_loop_new(worker_context, false);
worker_thread = thread(&executor::worker_loop, this);
}
~executor()
{
cout << "Stopping main loop" << endl;
GSource* idle_source = g_idle_source_new();
g_source_set_callback(idle_source, (GSourceFunc)g_main_loop_quit, main_loop, NULL);
g_source_attach(idle_source, worker_context);
g_source_unref(idle_source);
if (worker_thread.joinable())
{
worker_thread.join();
}
cout << "Removing references to main loop and context" << endl;
g_main_loop_unref(main_loop);
g_main_context_unref(worker_context);
}
void start()
{
queue_callback(func1);
queue_callback(func2);
}
};
int main()
{
executor e;
e.start();
return 0;
}
我知道你不能像那样传递非静态成员函数,所以,我得到了预期的编译错误。
test.cpp: In member function ‘void executor::start()’:
test.cpp:79:37: error: invalid use of non-static member function ‘int executor::func1()’
queue_callback(func1);
^
test.cpp:35:13: note: declared here
int func1()
^~~~~
test.cpp:80:37: error: invalid use of non-static member function ‘int executor::func2()’
queue_callback(func2);
^
test.cpp:43:13: note: declared here
int func2()
^~~~~
我看到有人用函数对象来包装成员函数。所以,我尝试了这个。
#include<glib.h>
#include<iostream>
#include<thread>
#include<chrono>
#include<functional>
using namespace std;
using namespace std::chrono_literals;
class executor
{
private:
GMainLoop* main_loop;
GMainContext* worker_context;
thread worker_thread;
void worker_loop()
{
g_main_context_push_thread_default(worker_context);
cout << "Starting main loop" << endl;
g_main_loop_run(main_loop);
cout << "Finished main loop" << endl;
g_main_context_pop_thread_default(worker_context);
}
void queue_callback(const function<int()>* callback)
{
GSource* idle_source = g_idle_source_new();
g_source_set_callback(idle_source, reinterpret_cast<GSourceFunc>(&on_callback), const_cast<function<int()>*>(callback), NULL);
g_source_attach(idle_source, worker_context);
g_source_unref(idle_source);
}
static int on_callback(const function<int()>* callback)
{
return (*callback)();
}
int func1()
{
cout << "func1 started" << endl;
this_thread::sleep_for(5s);
cout << "func1 finished waiting" << endl;
return 0;
}
int func2()
{
cout << "func2 started" << endl;
this_thread::sleep_for(1s);
cout << "func2 finished waiting" << endl;
return 0;
}
public:
executor()
{
worker_context = g_main_context_new();
main_loop = g_main_loop_new(worker_context, false);
worker_thread = thread(&executor::worker_loop, this);
}
~executor()
{
cout << "Stopping main loop" << endl;
GSource* idle_source = g_idle_source_new();
g_source_set_callback(idle_source, (GSourceFunc)g_main_loop_quit, main_loop, NULL);
g_source_attach(idle_source, worker_context);
g_source_unref(idle_source);
if (worker_thread.joinable())
{
worker_thread.join();
}
cout << "Removing references to main loop and context" << endl;
g_main_loop_unref(main_loop);
g_main_context_unref(worker_context);
}
void start()
{
cout << "Submitting func1 callback" << endl;
function<int()> callback1 = [this]() {
return func1();
};
queue_callback(&callback1);
cout << "Submitting func2 callback" << endl;
function<int()> callback2 = [this]() {
return func2();
};
queue_callback(&callback2);
}
};
int main()
{
executor e;
e.start();
return 0;
}
这段代码可以编译,但我总是遇到分段错误或 bad_function_call 异常。
Starting main loop
Submitting func1 callback
Submitting func2 callback
Stopping main loop
func1 started
func1 finished waiting
terminate called after throwing an instance of 'std::bad_function_call'
what(): bad_function_call
Aborted (core dumped)
我想我收到了错误,因为 callback1
和 callback2
是本地对象,当它们被执行时,它们的内存已被释放。
我该如何解决这个问题?我想过使用 unique_ptr
s,但无法弄清楚 g_source_set_callback
如何将 int (*GSourceFunc) void
作为第二个参数,将 void*
作为第三个参数。
我明白了。
我创建了一个新的 std::function
对象并将其传递给 g_source_set_callback
。当调用 on_callback
时,我将 void *
类型转换为 std::function<int()>*
,调用它并删除它。
这是工作代码。
#include<glib.h>
#include<iostream>
#include<thread>
#include<chrono>
#include<functional>
using namespace std;
using namespace std::chrono_literals;
class executor
{
private:
GMainLoop* main_loop;
GMainContext* worker_context;
thread worker_thread;
void worker_loop()
{
g_main_context_push_thread_default(worker_context);
cout << "Starting main loop" << endl;
g_main_loop_run(main_loop);
cout << "Finished main loop" << endl;
g_main_context_pop_thread_default(worker_context);
}
void queue_callback(function<int()>&& callback)
{
GSource* idle_source = g_idle_source_new();
g_source_set_callback(idle_source, on_callback, new function<int()>(callback), NULL);
g_source_attach(idle_source, worker_context);
g_source_unref(idle_source);
}
static int on_callback(void* ptr)
{
function<int()>* callback = static_cast<function<int()>*>(ptr);
int ret = (*callback)();
delete callback;
return ret;
}
int func1()
{
cout << "func1 started" << endl;
this_thread::sleep_for(5s);
cout << "func1 finished waiting" << endl;
return 0;
}
int func2()
{
cout << "func2 started" << endl;
this_thread::sleep_for(1s);
cout << "func2 finished waiting" << endl;
return 0;
}
public:
executor()
{
worker_context = g_main_context_new();
main_loop = g_main_loop_new(worker_context, false);
worker_thread = thread(&executor::worker_loop, this);
}
~executor()
{
cout << "Stopping main loop" << endl;
GSource* idle_source = g_idle_source_new();
g_source_set_callback(idle_source, (GSourceFunc)g_main_loop_quit, main_loop, NULL);
g_source_attach(idle_source, worker_context);
g_source_unref(idle_source);
if (worker_thread.joinable())
{
worker_thread.join();
}
cout << "Removing references to main loop and context" << endl;
g_main_loop_unref(main_loop);
g_main_context_unref(worker_context);
}
void start()
{
cout << "Submitting func1 callback" << endl;
queue_callback([this]() { return func1(); });
cout << "Submitting func2 callback" << endl;
queue_callback([this]() { return func2(); });
}
};
int main()
{
executor e;
e.start();
return 0;
}