Использование GLUT в объектно-ориентированной программе - PullRequest
2 голосов
/ 16 января 2012

Я настраиваю симулятор в C ++ для простой проблемной области.Основная механика написана в одном классе MountainCar.cpp, который хранит в качестве члена ссылку на графический интерфейс, который реализован в другом классе с именем MCViewer.cpp.Я имел приличное знакомство с GLUT, поэтому я решил вместо того, чтобы возиться с альтернативами, я мог бы просто создать то, что должно быть простым GUI, используя GLUT.Проблема в том, что у меня может быть запущено более одного моделирования одновременно, и я хочу, чтобы у каждого экземпляра был свой графический интерфейс.Это может быть общеизвестно, но GLUT - это C API, и определенные вызовы, которые мне нужны, такие как glutDisplayFunc и glutReshapeFunc, требуют указателей на функции C в качестве аргументов.Между тем мне нужно, чтобы поведение передаваемых функций зависело от некоторого произвольного экземпляра объекта MCViewer.

Я нашел здесь полезный поток в stackoverflow , который предлагал создавать и вместо этого передавать глобальные функции обратного вызова,при реализации соответствующих функций вызываемого абонента внутри класса MCViewer.Поскольку функции обратного вызова являются глобальными, но намереваются работать с некоторым указанным экземпляром объекта, необходима другая глобальная переменная, которая хранит ссылку на некоторый текущий объект MCViewer.

Результирующий заголовок:

#ifndef MCVIEWER_H__
#define MCVIEWER_H__

#include <cstdlib> 
#include <ctime>
#include <stdlib.h>
#include <string>
#include <math.h>
#include <iostream>
#include <assert.h>
#include <GLUT/GLUT.h>

class MCViewer {
    //MCViewer declarations, implementation specified in corresponding .cpp
};

extern MCViewer *currRef;

extern "C" {    
    static void displayFcnCB(void) {
        currRef->displayFcn();
    }

    static void winReshapeFcnCB(GLint newWidth, GLint newHeight) {
        currRef->winReshapeFcn(newWidth, newHeight);
    }

    static void keyboardActionCB(GLubyte key, GLint xMouse, GLint yMouse) {
        currRef->keyboardAction(key, xMouse, yMouse);
    }
}

#endif //MCVIEWER_H__

Проблема связана с включением этого файла в файлы MCViewer.cpp и MountainCar.h.Напомним, объект MountainCar, по моему замыслу, должен хранить ссылку на назначенный ему графический интерфейс.До того, как я сделал глобальные функции статичными и пометил глобальную переменную currRef extern, я изначально получал «дублирующие» ошибки во время компоновки.Теперь я получаю странную ошибку, которая говорит о том, что на currRef ссылаются как из MCViewer.o, так и из MountainCar.o.

Ответы [ 4 ]

1 голос
/ 16 января 2012

, но OpenGL - это C API, и определенные вызовы, такие как glutDisplayFunc и glutReshapeFunc, требуют указателей на функции C в качестве аргументов

Так? GLUT не является частью OpenGL, это просто сторонний фреймворк. Вы можете и фактически не должны использовать GLUT для чего-либо сложного.

1 голос
/ 16 января 2012

Возможно, вам удастся создать глобальную карту между идентификаторами окон и объектами GUI и использовать glutGetWindow для получения текущего идентификатора окна в глобальной функции отображения или изменения формы.

1 голос
/ 16 января 2012

Может быть, Qt подойдет вам лучше, если вы просто занимаетесь пользовательским интерфейсом, а не чертите сырье?

http://qt.nokia.com/

0 голосов
/ 16 января 2012

Я мог бы просто создать то, что должно быть простым GUI, используя GLUT.

Если вам нужен GUI, то я предлагаю использовать что-то еще. Qt инициализирует OpenGL и предоставляет мощную среду для кроссплатформенной разработки. На самом деле нет веской причины (я мог бы подумать) использовать GLUT для многооконных приложений.

extern MCViewer *currRef;

extern "C" {    
    static void displayFcnCB(void) {
        currRef->displayFcn();
    }

Вы избежите много неприятностей, если перестанете пытаться делать все в пределах заголовка.

До того, как я сделал глобальные функции статическими и пометил глобальную переменную currRef extern, я изначально получал "дублирующие" ошибки во время компоновки.

Статическое ключевое слово для функции, не являющейся членом, означает, что функция видима в одном файле * .cpp и не видна компоновщику. Поскольку вы включаете в заголовок статическую функцию , которая находится вне любого класса , у вас могут возникнуть проблемы. Удалите статическое ключевое слово, поместите тело функции в файл * .cpp и перешлите объявление в заголовок. Или держите это статичным и поместите это в класс. Или оставьте статическую функцию, не являющуюся членом, но удалите упоминания об этой функции из заголовков. Также вам не нужно использовать extern "C".

необходима еще одна глобальная переменная, в которой хранится ссылка на какой-то текущий объект MCViewer.

есть функция glutGetCurrentWindow, которая должна возвращать идентификатор текущего окна. Вместо того, чтобы пытаться передать параметры функции через глобальные переменные, используйте map (std::map или аналогичный) - это сопоставит идентификаторы окон с указателями классов «зрителя». Попытка передать параметры функции через глобальные переменные - это EXTREMELY плохая привычка программирования, которая сделает ваш код неуправляемым.

Тем не менее, в этот момент может быть лучше отказаться от GLUT и использовать другую среду графического интерфейса.

...