Как использовать Glad в DLL и exe

#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, и когда я пытаюсь экспортировать класс, он говорит, что не может найти методы суперкласса. Я отредактирую свой вопрос выше с помощью фрагмента кода, я знаю, что сейчас это другой вопрос, но все равно было бы здорово, если бы у вас было какое-то представление. Я отмечаю это как правильное, хотя, поскольку оно ответило на первоначальный вопрос 🙂