Linux使用小问题及解决办法

当遇到的问题出现不止一次的时候这篇文章就会很有用

但更多时候只是记录自己一次又一次的愚蠢XD

git pull 时报错

当远程版本更新后,在本地执行”git pull”可能会出现如下报错:

$ git pull

Updating... 
error: Your local changes to the following files would be overwritten by merge:

foo

Please commit your changes or stash them before you merge.

这个错误信息表明你在本地对 foo 文件做了修改,而这些修改没有被提交(commit),同时远程仓库中该文件也有更新。Git pull 试图合并远程的变更到你本地的仓库中,但是由于本地存在未提交的修改,Git 不知道应该如何处理这两个版本的差异,所以它停止了合并并显示了这个错误。

要解决这个问题,你有几个选择:

  1. 提交本地修改: 如果你想保留你本地的修改,并且之后再将这些修改合并到远程仓库的变更中,你可以先提交你的修改,然后再尝试 pull:

    git add foo
    git commit -m "描述你的修改"
    git pull
    

    如果在 pull 时遇到合并冲突,Git 会提示你解决它们。解决方法可能包括手动编辑冲突文件,选择保留哪个版本的更改,或者合并两边的更改。

  2. 暂存本地修改(Stashing): 如果你现在不想提交你的修改,可以使用 git stash 来临时保存它们,然后再进行 pull:

    git stash
    git pull
    git stash pop
    

    git stash pop 将恢复你之前暂存的修改。如果在恢复(pop)时遇到冲突,同样需要手动解决。

  3. 放弃本地修改: 如果你不想保留你本地的修改,想直接使用远程仓库的版本,可以通过以下命令丢弃本地的修改:

    git checkout -- foo
    git pull
    

    这将使用远程仓库中的文件版本覆盖本地的修改。

选择适合你情况的方法来解决这个问题。如果你不确定哪种方法更适合你,那么通常建议先暂存更改,因为这样你的本地修改不会丢失,并且你可以在 pull 之后决定如何处理这些修改。

如何将类内成员函数作为输入的函数指针参数

在 C++ 中,将成员函数用作回调函数通常会遇到问题,因为成员函数与普通的函数指针不同,成员函数是与特定对象的上下文相关联的。这意味着成员函数需要一个隐含的 this 指针,指向调用该成员函数的对象实例。因此,你不能直接将成员函数传递给期望普通函数指针的 API,如 GLFW 的回调设置函数。

为了在 GLFW 中使用类的成员函数作为回调,你需要一个兼容的函数签名和一种方法来传递 this 指针。一个常见的解决方案是使用静态成员函数或自由函数(非成员函数)作为回调,并在其中调用实例的成员函数。这通常涉及到设置一个全局指针或使用用户指针功能,如果 GLFW 支持的话。

这里是一个示例,展示了如何使用静态成员函数作为 GLFW 的回调:

class Application {
public:
    Application() {
        // 初始化 GLFW 窗口...

        // 设置用户指针,以便在静态回调函数中获取 Application 类的实例
        glfwSetWindowUserPointer(window, this);

        // 设置回调
        glfwSetFramebufferSizeCallback(window, Application::framebuffer_size_callback_wrapper);
        glfwSetCursorPosCallback(window, Application::mouse_callback_wrapper);
        glfwSetScrollCallback(window, Application::scroll_callback_wrapper);
    }

    static void framebuffer_size_callback_wrapper(GLFWwindow* window, int width, int height) {
        // 获取 Application 类的实例
        Application* app = static_cast<Application*>(glfwGetWindowUserPointer(window));
        if (app) {
            app->framebuffer_size_callback(window, width, height); // 调用实例的成员函数
        }
    }

    static void mouse_callback_wrapper(GLFWwindow* window, double xpos, double ypos) {
        Application* app = static_cast<Application*>(glfwGetWindowUserPointer(window));
        if (app) {
            app->mouse_callback(window, xpos, ypos);
        }
    }

    static void scroll_callback_wrapper(GLFWwindow* window, double xoffset, double yoffset) {
        Application* app = static_cast<Application*>(glfwGetWindowUserPointer(window));
        if (app) {
            app->scroll_callback(window, xoffset, yoffset);
        }
    }

    // 实例的成员函数
    void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
        // ...
    }

    void mouse_callback(GLFWwindow* window, double xpos, double ypos) {
        // ...
    }

    void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) {
        // ...
    }
};

在这个例子中,framebuffer_size_callback_wrappermouse_callback_wrapperscroll_callback_wrapper 是静态成员函数,它们可以被 GLFW 回调机制接受。这些函数使用 glfwGetWindowUserPointer 来获取之前通过 glfwSetWindowUserPointer 设置的 Application 类的实例指针,并调用相应的成员函数。

这种方法的关键在于确保在设置回调之前将 Application 实例的指针传递给 GLFW 窗口。这样,当回调被触发时,你可以访问到正确的实例并调用其成员函数。