Allow to instantiate HWEngine with different library binaries
authorunC0Rr
Fri, 07 Dec 2018 13:56:45 +0100
changeset 14377 b6824a53d4b1
parent 14376 90bd2c331703
child 14378 4409344db447
Allow to instantiate HWEngine with different library binaries
qmlfrontend/Page1.qml
qmlfrontend/engine_instance.cpp
qmlfrontend/engine_instance.h
qmlfrontend/engine_interface.h
qmlfrontend/hwengine.cpp
qmlfrontend/hwengine.h
qmlfrontend/main.cpp
--- a/qmlfrontend/Page1.qml	Fri Dec 07 13:35:08 2018 +0100
+++ b/qmlfrontend/Page1.qml	Fri Dec 07 13:56:45 2018 +0100
@@ -8,6 +8,7 @@
     id: hwEngineComponent
 
     HWEngine {
+      engineLibrary: "./libhedgewars_engine.so"
       previewAcceptor: PreviewAcceptor
       onPreviewImageChanged: previewImage.source = "image://preview/image"
       onPreviewIsRendering: previewImage.source = "qrc:/res/iconTime.png"
--- a/qmlfrontend/engine_instance.cpp	Fri Dec 07 13:35:08 2018 +0100
+++ b/qmlfrontend/engine_instance.cpp	Fri Dec 07 13:56:45 2018 +0100
@@ -1,6 +1,7 @@
 #include "engine_instance.h"
 
 #include <QDebug>
+#include <QLibrary>
 #include <QOpenGLFunctions>
 #include <QSurface>
 
@@ -12,37 +13,78 @@
     return currentOpenglContext->getProcAddress(fn);
 }
 
-EngineInstance::EngineInstance(QObject* parent)
-    : QObject(parent), m_instance(Engine::start_engine()) {}
+EngineInstance::EngineInstance(const QString& libraryPath, QObject* parent)
+    : QObject(parent) {
+  QLibrary hwlib(libraryPath);
+
+  if (!hwlib.load())
+    qWarning() << "Engine library not found" << hwlib.errorString();
+
+  hedgewars_engine_protocol_version =
+      reinterpret_cast<Engine::hedgewars_engine_protocol_version_t*>(
+          hwlib.resolve("hedgewars_engine_protocol_version"));
+  start_engine =
+      reinterpret_cast<Engine::start_engine_t*>(hwlib.resolve("start_engine"));
+  generate_preview = reinterpret_cast<Engine::generate_preview_t*>(
+      hwlib.resolve("generate_preview"));
+  cleanup = reinterpret_cast<Engine::cleanup_t*>(hwlib.resolve("cleanup"));
+
+  send_ipc = reinterpret_cast<Engine::send_ipc_t*>(hwlib.resolve("send_ipc"));
+  read_ipc = reinterpret_cast<Engine::read_ipc_t*>(hwlib.resolve("read_ipc"));
 
-EngineInstance::~EngineInstance() { Engine::cleanup(m_instance); }
+  setup_current_gl_context =
+      reinterpret_cast<Engine::setup_current_gl_context_t*>(
+          hwlib.resolve("setup_current_gl_context"));
+  render_frame =
+      reinterpret_cast<Engine::render_frame_t*>(hwlib.resolve("render_frame"));
+  advance_simulation = reinterpret_cast<Engine::advance_simulation_t*>(
+      hwlib.resolve("advance_simulation"));
+
+  m_isValid = hedgewars_engine_protocol_version && start_engine &&
+              generate_preview && cleanup && send_ipc && read_ipc &&
+              setup_current_gl_context && render_frame && advance_simulation;
+  emit isValidChanged(m_isValid);
+
+  if (isValid()) {
+    qDebug() << "Loaded engine library with protocol version"
+             << hedgewars_engine_protocol_version();
+
+    m_instance = start_engine();
+  }
+}
+
+EngineInstance::~EngineInstance() {
+  if (m_isValid) cleanup(m_instance);
+}
 
 void EngineInstance::sendConfig(const GameConfig& config) {
   for (auto b : config.config()) {
-    Engine::send_ipc(m_instance, reinterpret_cast<uint8_t*>(b.data()),
-                     static_cast<size_t>(b.size()));
+    send_ipc(m_instance, reinterpret_cast<uint8_t*>(b.data()),
+             static_cast<size_t>(b.size()));
   }
 }
 
 void EngineInstance::advance(quint32 ticks) {
-  Engine::advance_simulation(m_instance, ticks);
+  advance_simulation(m_instance, ticks);
 }
 
-void EngineInstance::renderFrame() { Engine::render_frame(m_instance); }
+void EngineInstance::renderFrame() { render_frame(m_instance); }
 
 void EngineInstance::setOpenGLContext(QOpenGLContext* context) {
   currentOpenglContext = context;
 
   auto size = context->surface()->size();
-  Engine::setup_current_gl_context(
-      m_instance, static_cast<quint16>(size.width()),
-      static_cast<quint16>(size.height()), &getProcAddress);
+  setup_current_gl_context(m_instance, static_cast<quint16>(size.width()),
+                           static_cast<quint16>(size.height()),
+                           &getProcAddress);
 }
 
 Engine::PreviewInfo EngineInstance::generatePreview() {
   Engine::PreviewInfo pinfo;
 
-  Engine::generate_preview(m_instance, &pinfo);
+  generate_preview(m_instance, &pinfo);
 
   return pinfo;
 }
+
+bool EngineInstance::isValid() const { return m_isValid; }
--- a/qmlfrontend/engine_instance.h	Fri Dec 07 13:35:08 2018 +0100
+++ b/qmlfrontend/engine_instance.h	Fri Dec 07 13:56:45 2018 +0100
@@ -1,31 +1,48 @@
 #ifndef ENGINEINSTANCE_H
 #define ENGINEINSTANCE_H
 
-#include "engine_interface.h"
-
 #include <QObject>
 #include <QOpenGLContext>
 
+#include "engine_interface.h"
 #include "game_config.h"
 
 class EngineInstance : public QObject {
   Q_OBJECT
  public:
-  explicit EngineInstance(QObject* parent = nullptr);
+  explicit EngineInstance(const QString& libraryPath,
+                          QObject* parent = nullptr);
   ~EngineInstance();
 
+  Q_PROPERTY(bool isValid READ isValid NOTIFY isValidChanged)
+
   void sendConfig(const GameConfig& config);
   void advance(quint32 ticks);
   void renderFrame();
   void setOpenGLContext(QOpenGLContext* context);
   Engine::PreviewInfo generatePreview();
 
+  bool isValid() const;
+
  signals:
+  void isValidChanged(bool isValid);
 
  public slots:
 
  private:
   Engine::EngineInstance* m_instance;
+
+  Engine::hedgewars_engine_protocol_version_t*
+      hedgewars_engine_protocol_version;
+  Engine::start_engine_t* start_engine;
+  Engine::generate_preview_t* generate_preview;
+  Engine::cleanup_t* cleanup;
+  Engine::send_ipc_t* send_ipc;
+  Engine::read_ipc_t* read_ipc;
+  Engine::setup_current_gl_context_t* setup_current_gl_context;
+  Engine::render_frame_t* render_frame;
+  Engine::advance_simulation_t* advance_simulation;
+  bool m_isValid;
 };
 
 #endif  // ENGINEINSTANCE_H
--- a/qmlfrontend/engine_interface.h	Fri Dec 07 13:35:08 2018 +0100
+++ b/qmlfrontend/engine_interface.h	Fri Dec 07 13:56:45 2018 +0100
@@ -36,18 +36,6 @@
 
 typedef bool advance_simulation_t(EngineInstance* engine_state, uint32_t ticks);
 
-extern hedgewars_engine_protocol_version_t* hedgewars_engine_protocol_version;
-extern start_engine_t* start_engine;
-extern generate_preview_t* generate_preview;
-extern cleanup_t* cleanup;
-
-extern send_ipc_t* send_ipc;
-extern read_ipc_t* read_ipc;
-
-extern setup_current_gl_context_t* setup_current_gl_context;
-extern render_frame_t* render_frame;
-extern advance_simulation_t* advance_simulation;
-
 #ifdef __cplusplus
 }
 };
--- a/qmlfrontend/hwengine.cpp	Fri Dec 07 13:35:08 2018 +0100
+++ b/qmlfrontend/hwengine.cpp	Fri Dec 07 13:56:45 2018 +0100
@@ -21,7 +21,10 @@
   m_gameConfig = GameConfig();
   m_gameConfig.cmdSeed(QUuid::createUuid().toByteArray());
 
-  EngineInstance engine;
+  EngineInstance engine(m_engineLibrary);
+  if (!engine.isValid())  // TODO: error notification
+    return;
+
   engine.sendConfig(m_gameConfig);
 
   Engine::PreviewInfo preview = engine.generatePreview();
@@ -52,7 +55,8 @@
   m_gameConfig.cmdTeam(team1);
   m_gameConfig.cmdTeam(team2);
 
-  EngineInstance* engine = new EngineInstance(this);
+  EngineInstance* engine = new EngineInstance(m_engineLibrary, this);
+
   return engine;
   // m_runQueue->queue(m_gameConfig);
 }
@@ -61,9 +65,18 @@
 
 PreviewAcceptor* HWEngine::previewAcceptor() const { return m_previewAcceptor; }
 
+QString HWEngine::engineLibrary() const { return m_engineLibrary; }
+
 void HWEngine::setPreviewAcceptor(PreviewAcceptor* previewAcceptor) {
   if (m_previewAcceptor == previewAcceptor) return;
 
   m_previewAcceptor = previewAcceptor;
   emit previewAcceptorChanged(m_previewAcceptor);
 }
+
+void HWEngine::setEngineLibrary(const QString& engineLibrary) {
+  if (m_engineLibrary == engineLibrary) return;
+
+  m_engineLibrary = engineLibrary;
+  emit engineLibraryChanged(m_engineLibrary);
+}
--- a/qmlfrontend/hwengine.h	Fri Dec 07 13:35:08 2018 +0100
+++ b/qmlfrontend/hwengine.h	Fri Dec 07 13:56:45 2018 +0100
@@ -18,6 +18,8 @@
                  previewHedgehogsCountChanged)
   Q_PROPERTY(PreviewAcceptor* previewAcceptor READ previewAcceptor WRITE
                  setPreviewAcceptor NOTIFY previewAcceptorChanged)
+  Q_PROPERTY(QString engineLibrary READ engineLibrary WRITE setEngineLibrary
+                 NOTIFY engineLibraryChanged)
 
  public:
   explicit HWEngine(QObject* parent = nullptr);
@@ -28,9 +30,11 @@
 
   int previewHedgehogsCount() const;
   PreviewAcceptor* previewAcceptor() const;
+  QString engineLibrary() const;
 
  public slots:
   void setPreviewAcceptor(PreviewAcceptor* previewAcceptor);
+  void setEngineLibrary(const QString& engineLibrary);
 
  signals:
   void previewIsRendering();
@@ -39,12 +43,14 @@
   void gameFinished();
   void previewHedgehogsCountChanged(int previewHedgehogsCount);
   void previewAcceptorChanged(PreviewAcceptor* previewAcceptor);
+  void engineLibraryChanged(const QString& engineLibrary);
 
  private:
   QQmlEngine* m_engine;
   GameConfig m_gameConfig;
   int m_previewHedgehogsCount;
   PreviewAcceptor* m_previewAcceptor;
+  QString m_engineLibrary;
 };
 
 #endif  // HWENGINE_H
--- a/qmlfrontend/main.cpp	Fri Dec 07 13:35:08 2018 +0100
+++ b/qmlfrontend/main.cpp	Fri Dec 07 13:56:45 2018 +0100
@@ -8,17 +8,7 @@
 #include "hwengine.h"
 #include "preview_acceptor.h"
 
-namespace Engine {
-hedgewars_engine_protocol_version_t* hedgewars_engine_protocol_version;
-start_engine_t* start_engine;
-generate_preview_t* generate_preview;
-cleanup_t* cleanup;
-send_ipc_t* send_ipc;
-read_ipc_t* read_ipc;
-setup_current_gl_context_t* setup_current_gl_context;
-render_frame_t* render_frame;
-advance_simulation_t* advance_simulation;
-};  // namespace Engine
+namespace Engine {};  // namespace Engine
 
 static QObject* previewacceptor_singletontype_provider(
     QQmlEngine* engine, QJSEngine* scriptEngine) {
@@ -28,50 +18,10 @@
   return acceptor;
 }
 
-void loadEngineLibrary() {
-#ifdef Q_OS_WIN
-  QLibrary hwlib("./libhedgewars_engine.dll");
-#else
-  QLibrary hwlib("./libhedgewars_engine.so");
-#endif
-
-  if (!hwlib.load())
-    qWarning() << "Engine library not found" << hwlib.errorString();
-
-  Engine::hedgewars_engine_protocol_version =
-      reinterpret_cast<Engine::hedgewars_engine_protocol_version_t*>(
-          hwlib.resolve("hedgewars_engine_protocol_version"));
-  Engine::start_engine =
-      reinterpret_cast<Engine::start_engine_t*>(hwlib.resolve("start_engine"));
-  Engine::generate_preview = reinterpret_cast<Engine::generate_preview_t*>(
-      hwlib.resolve("generate_preview"));
-  Engine::cleanup =
-      reinterpret_cast<Engine::cleanup_t*>(hwlib.resolve("cleanup"));
-
-  Engine::send_ipc =
-      reinterpret_cast<Engine::send_ipc_t*>(hwlib.resolve("send_ipc"));
-  Engine::read_ipc =
-      reinterpret_cast<Engine::read_ipc_t*>(hwlib.resolve("read_ipc"));
-
-  Engine::setup_current_gl_context =
-      reinterpret_cast<Engine::setup_current_gl_context_t*>(
-          hwlib.resolve("setup_current_gl_context"));
-  Engine::render_frame =
-      reinterpret_cast<Engine::render_frame_t*>(hwlib.resolve("render_frame"));
-  Engine::advance_simulation = reinterpret_cast<Engine::advance_simulation_t*>(
-      hwlib.resolve("advance_simulation"));
-
-  if (Engine::hedgewars_engine_protocol_version)
-    qDebug() << "Loaded engine library with protocol version"
-             << Engine::hedgewars_engine_protocol_version();
-}
-
 int main(int argc, char* argv[]) {
   QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
   QGuiApplication app(argc, argv);
 
-  loadEngineLibrary();
-
   QQmlApplicationEngine engine;
 
   qmlRegisterSingletonType<PreviewAcceptor>(