title: OpenGL Wrapper in C#
body: <p>I wrote a simple class to create a window and initialize OpenGL to that window. It works fine in native c++ and in CLI as well. But as soon as I import the CLI class as DLL into my C# project the rendering fails. A blank window shows up but the rendering doesn't work. The SwapBuffers and the GL rendering get called but nothing happens. Do you have any idea what can be wrong?
  (Sorry I am not a native speaker)</p>
  
  <p><strong>OpenGLClass.cpp</strong></p>
  
  <pre><code>#include "OpenGLClass.h"
  #include &lt;iostream&gt;
  
  LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
  
  OpenGLClass::OpenGLClass()
  {
  }
  
  
  OpenGLClass::~OpenGLClass()
  {
  }
  
  bool OpenGLClass::Initialize()
  {
      if (InitWindow())
          return InitOGL();
      else
          return false;
  }
  
  void OpenGLClass::Run()
  {
      MSG msg = { 0 };
      while (true)
      {
          if (PeekMessage(&amp;msg, NULL, NULL, NULL, PM_REMOVE))
          {
              if (msg.message == WM_QUIT)
                  break;
  
              TranslateMessage(&amp;msg);
              DispatchMessage(&amp;msg);
          }
          else
          {
              Render();
              SwapBuffers(m_hDevContext);
          }
      }
  }
  
  void OpenGLClass::Render()
  {
      glViewport(0, 0, 800, 600);
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      gluPerspective(45.0, (float)800 / (float)600, 1, 1000);
  
      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();
  
      gluLookAt(0, 0, 10,
          0, 0, 0,
          0, 1, 0);
  
      glClearColor(0.2, 0.5, 0.8, 1.0);
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  
      static float i = 0.01f;
  
      i += 0.001f;
  
      float c = cos(i);
      float s = sin(i);
  
      glBegin(GL_TRIANGLES);
      glColor3f(c, 0, 0);      // red
      glVertex3f(1 + c, 0 + s, 0);
  
      glColor3f(c, s, 0);      // yellow
      glVertex3f(0 + c, 1 + s, 0);
  
      glColor3f(s, 0.1f, s);   // magenta
      glVertex3f(-1 + c, 0 + s, 0);
      glEnd();
  }
  
  bool OpenGLClass::InitWindow()
  {
      WNDCLASSEX wc;
  
      m_hInstance = GetModuleHandle(NULL);
  
      wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
      wc.lpfnWndProc = WndProc;
      wc.cbClsExtra = 0;
      wc.cbWndExtra = 0;
      wc.hInstance = m_hInstance;
      wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
      wc.hIconSm = wc.hIcon;
      wc.hCursor = LoadCursor(NULL, IDC_ARROW);
      wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
      wc.lpszMenuName = NULL;
      wc.lpszClassName = "OpenGLWindow";
      wc.cbSize = sizeof(WNDCLASSEX);
  
      if (!RegisterClassEx(&amp;wc))
      {
          MessageBox(NULL, "RegisterClassEx() failed", "Error", MB_OK);
          return false;
      }
  
      int screenWidth = GetSystemMetrics(SM_CXSCREEN);
      int screenHeight = GetSystemMetrics(SM_CYSCREEN);
  
      screenWidth = 800;
      screenHeight = 600;
      int nStyle = WS_POPUP;
  
  
      m_hwnd = CreateWindowEx(WS_EX_APPWINDOW, "OpenGLWindow", "WindowTitle", nStyle, 0, 0, screenWidth, screenHeight, NULL, NULL, m_hInstance, NULL);
  
  
      ShowWindow(m_hwnd, SW_SHOW);
      return true;
  }
  
  bool OpenGLClass::InitOGL()
  {
      m_hDevContext = GetDC(m_hwnd);
  
  
      PIXELFORMATDESCRIPTOR pfd = { 0 };
      pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
      pfd.nVersion = 1;
      pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
      pfd.iPixelType = PFD_TYPE_RGBA;
      pfd.cColorBits = 32;
      pfd.cDepthBits = 24;
      pfd.cStencilBits = 24;
  
      int format = ChoosePixelFormat(m_hDevContext, &amp;pfd);
      if (format == 0)
          return false;
  
      std::cout &lt;&lt; "Pixel Format: " &lt;&lt; format &lt;&lt; std::endl;
  
      if (!SetPixelFormat(m_hDevContext, format, &amp;pfd))
          return false;
  
  
      m_GLRenderContext = wglCreateContext(m_hDevContext);
      if (!wglMakeCurrent(m_hDevContext, m_GLRenderContext))
          return false;
      GLint GlewInitResult = glewInit();
      if (GLEW_OK != GlewInitResult)
      {
          return false;
      }
  
      glEnable(GL_DEPTH_TEST);
      glEnable(GL_CULL_FACE);
      glCullFace(GL_BACK);
  
  
      return true;
  }
  
  LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  {
      PAINTSTRUCT ps;
      HDC hdc;
  
      switch (message)
      {
      case WM_KEYDOWN:
          if (wParam == VK_ESCAPE)
          {
              PostQuitMessage(0);
              DestroyWindow(hwnd);
          }
          break;
      case WM_CLOSE:
          PostQuitMessage(0);
          DestroyWindow(hwnd);
          break;
  
      default:
          return DefWindowProc(hwnd, message, wParam, lParam);
      }
  
      return 0;
  }
  </code></pre>
  
  <p><strong>WrapperClass.h</strong></p>
  
  <pre><code>#pragma once
  #include &lt;OpenGLClass.h&gt;
  
  public ref class WrapperClass
  {
  public:
      WrapperClass() : m_Impl(new OpenGLClass) {}
  
      ~WrapperClass() {
          delete m_Impl;
      }
  
  protected:
      !WrapperClass() {
          delete m_Impl;
      }
  
  public:
  
      inline bool Initialize()
      {
          return m_Impl-&gt;Initialize();
      }
  
  
      inline void Run()
      {
          m_Impl-&gt;Run();
      }
  
  private:
      OpenGLClass* m_Impl;
  };
  </code></pre>
  
  <p><strong>The C# code</strong></p>
  
  <pre><code>namespace WindowsFormsApp1
  {
      public partial class Form1 : Form
      {
          BackgroundWorker bw = new BackgroundWorker();
          WrapperClass wc;
  
          public Form1()
          {
              InitializeComponent();
              InitOGL();
          }
  
          private void InitOGL()
          {
              wc = new WrapperClass();
              if(wc.Initialize())
              {
                  bw.DoWork += Bw_DoWork;
                  bw.RunWorkerAsync();
              }
          }
  
          private void Bw_DoWork(object sender, DoWorkEventArgs e)
          {
              wc.Run();
          }
      }
  }
  </code></pre>