#c #opengl #dll #glfw #glad
#c #opengl #dll #glfw #glad
Вопрос:
Есть ли какой-либо способ использовать Glad в DLL и exe? Я чувствую, что могут возникнуть проблемы, поскольку у DLL есть собственное пространство памяти, отдельное от exe, но я не уверен, как бы я перестроил свой код, чтобы представить это.
Моя ситуация такова, что у меня есть игровой движок, который содержит множество методов, которые используют функции OpenGL, загружаемые glad, такие как шейдеры, текстуры и все остальное, что связано с рендерингом. Но я экспортирую движок как dll (по разным другим причинам), и редактор среды выполнения ссылается на эту dll. Этот редактор среды выполнения также требует доступа к функциям glad, потому что он статически ссылается на imgui, для которого требуется тот же контекст окна и все остальное, и я предполагаю, что если бы я вызвал gladLoadGL() в dll и в exe, я бы получил разные указатели на функции, что означает, что они не будут работать с одними и теми же данными. Есть ли какой-либо способ сделать это? Я также пытался связать GLFW как DLL, но это не помогает (что имеет смысл, поскольку это проблема glad). Если я не выполняю gladLoadGL() в своем exe, я получаю исключения nullptr при попытке выполнить функции gl (потому что есть всего пара случаев, когда я использую glFunctions внутри редактора времени выполнения). Но если я запускаю gladLoadGL() в моем exe, он загружает новые указатели на функции, которые отключают все, и я получаю ошибки внутри ImGui, которые, как я предполагаю, вызваны тем, что glad загрузил разные указатели на функции в DLL и exe.
Можно ли это сделать, или мне нужно переосмыслить мою общую архитектуру?
Редактировать: Итак, на мой первоначальный вопрос был дан ответ, и вам не нужно делать ничего особенного (кроме загрузки функций glad в DLL и exe). Однако это вызывает новую проблему в моем коде, которая, похоже, и была настоящей проблемой. Прямо сейчас у меня есть класс в DLL, который выглядит примерно так:
// In the DLL
class __declspec(dllexport) Application
{
Application();
void Construct(); // I added this because the base constructor would not be called
virtual void SomeFunc() {} // These are overridden by whoever inherits this class
virtual void SomeOtherFunc() {}
}
// In the exe
class MyApp : public Application
{
MyApp()
{
Construct() // This raises a runtime exception that says the method could not be found.
//Is there any way to make sure I export and import this correctly as well?
}
}
Редактировать 2: оказывается, я просто пропустил шаг сборки и никогда не копировал свою dll туда, где находился exe. Еще раз спасибо за всю помощь, хотя
Комментарии:
1. » Я бы получил разные указатели на функции, что означает, что они не будут работать с одними и теми же данными » Почему вы думаете, что это было бы так?
2. @NicolBolas Потому что dll имеет свою собственную виртуальную память. Итак, когда dll вызывает glLoad, она загружает указатели на функции в свое пространство памяти, затем, когда я вызываю glLoad в exe, она загружает новые указатели на функции в свое пространство памяти. Если я правильно понимаю, как библиотеки DLL выполняются в операционной системе, не стесняйтесь поправлять меня, если я ошибаюсь.
3. Ну, ваше понимание неверно. Правильно, что если вы не экспортируете указатели функций glad из своей библиотеки DLL, вам понадобится отдельный набор для остальных, но это не имеет никакого отношения к пространствам памяти (и весь процесс будет использовать свое собственное адресное пространство, а не каждую загружаемую библиотеку), но с видимостью символов во время динамической компоновки. Указатели на функции GL относятся к GL-контексту (или даже фактически к ICD в Windows), поэтому вы получите те же указатели на функции, если вы запросите их для одного и того же контекста.
Ответ №1:
Важно помнить различие между переменной-указателем и тем, на что она указывает. Если у вас есть один экземпляр GLAD в DLL, а другой в EXE, то для каждого указателя функции GLAD у вас будет две переменные указателя.
Однако оба они будут указывать на одну и ту же функцию. В конце концов, они загружают указатели на функции для одного и того же контекста OpenGL. Таким образом, эти указатели будут указывать на одни и те же функции.
Таким образом, хотя технически вы потратите впустую некоторый объем хранилища (поскольку и DLL, и EXE нуждаются в переменных указателя), он все равно должен нормально функционировать, если контекст OpenGL является текущим при загрузке указателей.
Комментарии:
1. Спасибо @NicolBolas . Это сузило круг поиска для меня, оказывается, я не создавал контекст в DLL. Однако это вызывает у меня другой вопрос. Прямо сейчас у меня есть подкласс в exe, наследующий от суперкласса в dll, и когда я пытаюсь экспортировать класс, он говорит, что не может найти методы суперкласса. Я отредактирую свой вопрос выше с помощью фрагмента кода, я знаю, что сейчас это другой вопрос, но все равно было бы здорово, если бы у вас было какое-то представление. Я отмечаю это как правильное, хотя, поскольку оно ответило на первоначальный вопрос 🙂