CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 15 of 16

Threaded View

  1. #1
    Join Date
    Jul 2017
    Location
    Greece
    Posts
    130

    C++ Library with DLL exports for hiding implementation.

    After a long time of asking you about DLLs, I think I'm finally ready to move on with my project. I'm creating a game engine which I'm going to use to make a game. But this game engine is going to be also an API for those who wish to make their own games, and also extensible in order for others to be able to extend (Create Modes) a game made by this game engine, with dynamic loading. One of the obstacles I found along the way was to hide the Graphics implementation which is very low level and the Client doesn't need to use. Also another reason I want to hide the graphics implementation is because I don't want the Client to compile and Link against the Libraries which I'm using.

    My engine's API is going to be defined into header files only because it's c++ (So i won't have compatibility problems with DLL exporting). The graphics code, since the Libraries which I'm using are all in pure c dlls, I decided to do a trick of hiding the implementation into .cpp files which contain only c functions and compile those to a dll. So the user only needs to include my header files and link against that dll in order to use my library.

    I want to make sure that everything is well structured and defined for compatibility so I'm inviting you to check that for me. I will demonstrate to you some code of my project to show you if I'm doing everything OK.

    To give you a quick overview, basically what I'm doing is that code which I want to hide and it's pure c, i'm coding it into a cpp file and I'm declaring those function as extern "C" in order to export them into a dll.
    Then into my header file, i'm declaring my class (which the clientis going to use) by calling these extern functions. The client is going to use only the Window Class.

    Window Class
    Code:
    #ifndef VAMP_ENGINE_WINDOW_H
    #define VAMP_ENGINE_WINDOW_H
    #include <iostream>
    #include "ExportDLL.h"
    
    struct GLFWwindow;
    
    namespace VampEngine
    {
    	//-_-_-_-_-_-_-_-_-_-Declarations-_-_-_-_-_-_-_-_-_-//
    
    	//Classes.
    	class WindowImpl;
    
    	//WindowImpl Class Functions.
    	extern "C" VAMP_ENGINE_EXPORT int InitializeWindowImpl(WindowImpl *window, std::string title, unsigned int width, unsigned int height);
    	extern "C" VAMP_ENGINE_EXPORT int DestroyWindowImpl(WindowImpl *window);
    
    	//Core Class Functions.
    	extern "C" VAMP_ENGINE_EXPORT int MainLoopImpl(WindowImpl *window);
    
    	//-_-_-_-_-_-_-_-_-_-Declarations-_-_-_-_-_-_-_-_-_-//
    
    	///WindowImpl Struct.
    	/**
    	You SHOULD NOT instantiate an instance of this struct!
    	The Application handle's instances of this struct
    	automatically.
    	*/
    	class WindowImpl
    	{
    
    		//Friends.
    		friend class Window;
    		friend class Core;
    
    	//Private Members.
    	private:
    		GLFWwindow *m_GLFWwindow;
    		const char *m_Error;
    		const char *m_Title;
    		int m_Width, m_Height;
    
    	//Function Friends.
    	public:
    		friend int InitializeWindowImpl(WindowImpl *window, std::string title, unsigned int width, unsigned int height);
    		friend int DestroyWindowImpl(WindowImpl *window);
    		friend int VampEngine::MainLoopImpl(WindowImpl *window);
    	};
    
    	///Window Class.
    	/**
    	You SHOULD NOT instantiate an instance of this class!
    	The Application handle's instances of this class
    	automatically.
    	*/
    	class Window
    	{
    
    		//Friends.
    		friend class Core;
    
    	//Private Members.
    	private:
    
    		WindowImpl *m_PtrToImpl;
    
    
    
    	//Public Methods.
    	public:
    
    		///Constrcutor.
    		Window(std::string title, unsigned int width, unsigned int height)
    		{
    			//Create and initialize the Window.
    			m_PtrToImpl = new WindowImpl();
    			int error   = InitializeWindowImpl(m_PtrToImpl, title, width, height);
    
    			//Initialization Failed.
    			if (error) throw m_PtrToImpl->m_Error;
    		}
    
    		///Deconstructor.
    		~Window() 
    		{
    			//Destroy the implementation.
    			DestroyWindowImpl(m_PtrToImpl);
    		}
    
    		///GetWidth() Method.
    		/**
    		Return's the width of the window.
    		*/
    		inline int GetWidth() { return m_PtrToImpl->m_Width; }
    
    		///GetHeight() Method.
    		/**
    		Return's the height of the window.
    		*/
    		inline int GetHeight() { return m_PtrToImpl->m_Height; }
    
    		///GetTitle() Method.
    		/**
    		Return's the title of the window.
    		*/
    		inline std::string GetTitle() { return m_PtrToImpl->m_Title; }
    
    	};
    }
    
    #endif

    Window Graphics Implementation
    Code:
    #include "Window.hpp"
    #include <GL/glew.h>
    #include <GLFW/glfw3.h>
    
    
    //Constructor.
    int VampEngine::InitializeWindowImpl(WindowImpl *window, std::string title, unsigned int width, unsigned int height)
    {
    
    	//----------Initialize----------//
    	window->m_Error  = "";
    	window->m_Width  = width;
    	window->m_Height = height;
    	window->m_Title  = title.c_str();
    
    	/* Initialize the library */
    	if (!glfwInit())
    	{
    		window->m_Error = "GLFW failed to be initialized.";
    		return 1;
    	}
    
    	/* Create a windowed mode window and its OpenGL context */
    	window->m_GLFWwindow = glfwCreateWindow(width, height, title.c_str(), NULL, NULL);
    	if (!window->m_GLFWwindow)
    	{
    		window->m_Error = "GLFW failed to create a Window.";
    		glfwTerminate();
    		return 1;
    	}
    
    	/* Make the window's context current */
    	glfwMakeContextCurrent(window->m_GLFWwindow);
    
    	//Initialize Glew.
    	if (glewInit() != GLEW_OK)
    	{
    		window->m_Error = "GLEW failed to be initialized.";
    		glfwDestroyWindow(window->m_GLFWwindow);
    		glfwTerminate();
    		return 1;
    	}
    
    	//Succeeded.
    	return 0;
    }
    
    
    
    
    //Deconstructor.
    int VampEngine::DestroyWindowImpl(WindowImpl *window)
    {
    
    	//Destroy GLFW Window.
    	glfwDestroyWindow(window->m_GLFWwindow);
    
    	//Terminate GLFW.
    	glfwTerminate();
    
    	//Delete the window.
    	delete window;
    
    	//Succeeded.
    	return 0;
    }
    The code is working fine, but I would like to take some advises from you about compatibility.

    Also, I want to ask about the function extern "C" VAMP_ENGINE_EXPORT int MainLoopImpl(WindowImpl *window);
    This is a function from another file, but I'm also declaring it on Window.hpp because I need to make it friend to the WindowImpl class.
    The compiler is warning me about inconsistent dll linkage . On google i found that this warning is mostly generated when you have duplicates
    of __declspec() function definitions. Will I have a problem with that? I'm 100% sure that both definitions will have __declspec(dllexport)
    when compiling the dll and __declspec(dllimport) when the Client include's the header file. (the macro VAMP_ENGINE_EXPORT is responsible for the __declspec()) .

    Thank you.
    Last edited by babaliaris; December 4th, 2018 at 01:42 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured