热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

在D到C函数中,类方法回调。-ClassmethodcallbacksinDtoCfunctions

Imwritingasimple,lightweightengineinD.FortheinputcallsIuseGLFW3.Thelibraryinquest

I'm writing a simple, lightweight engine in D. For the input calls I use GLFW3. The library in question uses callbacks to send input events to the program.

我在d中编写了一个简单的轻量级引擎,用于输入调用GLFW3。该库使用回调函数将输入事件发送到程序。

What I would like is to use a method from a class as the callback function, rather than a function. This is proving difficult (just as it is in C++). I believe there is an elegant way to do it, but this is how I got it right now.

我想要的是使用一个类的方法作为回调函数,而不是函数。事实证明这是困难的(就像在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);
}

Here is the definition of the callback setting function and type:

下面是回调设置函数和类型的定义:

extern (C) {
    alias              GLFWkeyfun = void function(GLFWwindow*, int, int, int, int);
    GLFWkeyfun         glfwSetKeyCallback(GLFWwindow*, GLFWkeyfun);
}

What I would like to do instead, is create a method that is part of the class. Is there any way to do this?

我想要做的是创建一个方法,它是类的一部分。有什么办法吗?

A solution I tried was a static method wrapped around in extern (C), this worked for calling it, but then I could (obviously) not access this or any other methods, which defeats the point of the exercise.

我尝试过的一个解决方案是在外部(C)中封装的静态方法,这个方法可以调用它,但是我可以(很明显)不能访问这个或任何其他方法,这就违背了这个练习的要点。

Thanks in advance.

提前谢谢。

2 个解决方案

#1


0  

The way I'd do it is to have a static map of the pointers to the class, so like:

我这样做的方法是有一个指向类的指针的静态映射,比如:

static YourWindowClass[GLFWwindow*] mappings;

Then, in the constructor, once you get a GLFWwindow pointer, add it right in:

然后,在构造函数中,一旦获得了一个GLFWwindow指针,就将它添加到:

mappings[m_Window.window] = this;

Now, make the static extern(C) function to use as the callback. When it gets a pointer from C, look up your class reference in that mappings array and then go ahead and call the member function through that, forwarding the arguments.

现在,让静态外部(C)函数用作回调函数。当它从C获取一个指针时,在那个映射数组中查找你的类引用,然后通过它调用成员函数,转发参数。

So a bit of an extra step, but since it doesn't look like the callback lets you pass user-defined data to it (BTW, attention all lib writers: user-defined void* to the callbacks is sooooo useful, you should do it whenever possible!), but since it doesn't do that the associative array is the next best thing.

所以一个额外的步骤,但是因为它看起来不像它的回调函数可以通过用户定义的数据(顺便说一句,所有自由作家注意:用户定义的回调函数void *是如此的有用,你应该尽可能地做到!),但由于没有关联数组是再好不过的事情了。

#2


0  

Well, I have figured it out my own. The solution I went with was a Singleton class InputManager. Instances of RenderWindow attach themselves to it with the following function. The InputManager then creates an anonymous function() for the RenderWindow that receives events, which then calls a function that handles the actual event.

嗯,我自己也算出来了。我使用的解决方案是一个独立类InputManager。RenderWindow的实例与下面的函数连接在一起。然后InputManager为接收事件的RenderWindow创建一个匿名函数(),然后调用一个处理实际事件的函数。

The idea is then that listeners attach themselves to the InputManager and receive keyboard events for the RenderWindow they requested.

然后,侦听器将自己连接到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
    }
}

Works like a charm, now to figure out how to properly attach listeners elegantly.

像符咒一样工作,现在想办法正确地连接听众。

For those curious, the full source code with how this is set up can be found at https://github.com/Adel92/Mage2D. I hope it helps someone else in a similar position with callbacks.

对于那些好奇的人,可以在https://github.com/Adel92/Mage2D中找到完整的源代码。我希望它能帮助其他人在类似的岗位上有回调。


推荐阅读
  • 1简介本文结合数字信号处理课程和Matlab程序设计课程的相关知识,给出了基于Matlab的音乐播放器的总体设计方案,介绍了播放器主要模块的功能,设计与实现方法.我们将该设 ... [详细]
  • IjustinheritedsomewebpageswhichusesMooTools.IneverusedMooTools.NowIneedtoaddsomef ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文详细介绍了Android中的坐标系以及与View相关的方法。首先介绍了Android坐标系和视图坐标系的概念,并通过图示进行了解释。接着提到了View的大小可以超过手机屏幕,并且只有在手机屏幕内才能看到。最后,作者表示将在后续文章中继续探讨与View相关的内容。 ... [详细]
  • wpf+mvvm代码组织结构及实现方式
    本文介绍了wpf+mvvm代码组织结构的由来和实现方式。作者回顾了自己大学时期接触wpf开发和mvvm模式的经历,认为mvvm模式使得开发更加专注于业务且高效。与此同时,作者指出mvvm模式相较于mvc模式的优势。文章还提到了当没有mvvm时处理数据和UI交互的例子,以及前后端分离和组件化的概念。作者希望能够只关注原始数据结构,将数据交给UI自行改变,从而解放劳动力,避免加班。 ... [详细]
  • 概述H.323是由ITU制定的通信控制协议,用于在分组交换网中提供多媒体业务。呼叫控制是其中的重要组成部分,它可用来建立点到点的媒体会话和多点间媒体会议 ... [详细]
  • vue使用
    关键词: ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 本文介绍了一个题目的解法,通过二分答案来解决问题,但困难在于如何进行检查。文章提供了一种逃逸方式,通过移动最慢的宿管来锁门时跑到更居中的位置,从而使所有合格的寝室都居中。文章还提到可以分开判断两边的情况,并使用前缀和的方式来求出在任意时刻能够到达宿管即将锁门的寝室的人数。最后,文章提到可以改成O(n)的直接枚举来解决问题。 ... [详细]
  • Ihavethefollowingonhtml我在html上有以下内容<html><head><scriptsrc..3003_Tes ... [详细]
  • Imtryingtofigureoutawaytogeneratetorrentfilesfromabucket,usingtheAWSSDKforGo.我正 ... [详细]
  • iOS Swift中如何实现自动登录?
    本文介绍了在iOS Swift中如何实现自动登录的方法,包括使用故事板、SWRevealViewController等技术,以及解决用户注销后重新登录自动跳转到主页的问题。 ... [详细]
  • 本文介绍了利用ARMA模型对平稳非白噪声序列进行建模的步骤及代码实现。首先对观察值序列进行样本自相关系数和样本偏自相关系数的计算,然后根据这些系数的性质选择适当的ARMA模型进行拟合,并估计模型中的位置参数。接着进行模型的有效性检验,如果不通过则重新选择模型再拟合,如果通过则进行模型优化。最后利用拟合模型预测序列的未来走势。文章还介绍了绘制时序图、平稳性检验、白噪声检验、确定ARMA阶数和预测未来走势的代码实现。 ... [详细]
author-avatar
loloyoyo555
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有