[英]Class method callbacks in D to C functions
我在D中编写了一个简单,轻量级的引擎。对于输入调用,我使用GLFW3。 有问题的库使用回调将输入事件发送到程序。
我想要的是使用类中的方法作为回调函数,而不是函数。 事实证明这很困难(就像C ++中一样)。 我相信有一种优雅的方法可以做到这一点,但这就是我现在的方法。
public void initialise(string logPath) {
[...]
m_Window = new RenderWindow();
m_Window.create();
// Lets set up the input loop.
GLFWkeyfun keyCB = function(GLFWwindow* win, int key, int scancode, int action, int mods) {
printf("Got key event: %d:%d:%d:%d\n");
RenderWindow rw = Root().getRenderWindow();
switch (key) {
case KeyboardKeyID.Q:
glfwSetWindowShouldClose(win, true);
break;
case KeyboardKeyID.H:
if (rw.hidden) {
rw.show();
} else {
rw.hide();
}
break;
default:
break;
}
};
glfwSetKeyCallback(m_Window.window, keyCB);
}
这是回调设置函数和类型的定义:
extern (C) {
alias GLFWkeyfun = void function(GLFWwindow*, int, int, int, int);
GLFWkeyfun glfwSetKeyCallback(GLFWwindow*, GLFWkeyfun);
}
我想做的是创建一个属于类的方法。 有什么办法吗?
我尝试过的一个解决方案是在extern (C)
包裹一个static
方法,该方法可以调用它,但是后来我(显然)无法访问this
方法或任何其他方法,这不符合本练习的要点。
提前致谢。
我这样做的方法是拥有指向该类的指针的静态映射,如下所示:
static YourWindowClass[GLFWwindow*] mappings;
然后,在构造函数中,一旦获得GLFWwindow指针,请在以下位置添加它:
mappings[m_Window.window] = this;
现在,使静态extern(C)函数用作回调。 当它从C获取指针时,请在该映射数组中查找类引用,然后继续通过它调用成员函数,并转发参数。
因此,这是一个额外的步骤,但是由于它看起来不像回调使您可以将用户定义的数据传递给它(顺便说一句,请注意所有lib编写器:用户定义的void *对回调非常有用,您应该这样做只要有可能就可以!),但由于这样做不行,所以关联数组是下一个最好的选择。
好吧,我自己解决了。 我使用的解决方案是Singleton类InputManager
。 RenderWindow
实例通过以下函数将其自身附加到它。 然后, InputManager
为接收事件的RenderWindow
创建一个匿名function()
,然后该匿名function()
调用一个处理实际事件的函数。
然后的想法是,侦听器将自己附加到InputManager
并接收他们请求的RenderWindow
键盘事件。
class InputManager {
private static InputManager m_Instance;
private RenderWindow[] m_Watched;
private KeyboardListener[][RenderWindow] m_KeyListeners;
public void recvKeyEvent(GLFWwindow* w, int k, int c, int a, int m) {
writeln("Received key: ", k);
}
public void watch(RenderWindow win) {
if (!isWatched(win)) {
// Relay the key callbacks onto the InputManager.
GLFWkeyfun keyCB = function(GLFWwindow* w, int k, int c, int a, int m) {
InputManager().recvKeyEvent(w, k, c, a, m);
};
glfwSetKeyCallback(win.window, keyCB);
}
}
private bool isWatched(RenderWindow win) {
foreach(RenderWindow w; m_Watched) {
if (win == w) {
return true;
}
}
return false;
}
public static InputManager opCall() {
if (m_Instance is null) {
m_Instance = new InputManager();
}
return m_Instance;
}
private this() {
// nothing
}
}
现在就像魅力一样工作,以弄清楚如何正确地优雅地吸引听众。
对于那些好奇的人,可以在https://github.com/Adel92/Mage2D中找到有关如何设置的完整源代码。 我希望它可以帮助其他处于类似位置的人使用回调。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.