1

I am loading OpenGL in C# using LoadLibrary/GetProcAddress/wglGetProcAddress. For some reason, it fails to load the pointer for glBlendFunc, and other random ones after that point. I have been looking through my code for the better part of an hour now, and all these failing parts look completely fine and normal?

The code to load the function pointers and cast it to a delegate.

    public override T GetFunction<T>(string name)
    {
        IntPtr pointer = wglGetProcAddress(name);
        if (pointer == IntPtr.Zero)
            pointer = GetProcAddress(Handle, name);
        return Marshal.GetDelegateForFunctionPointer<T>(pointer);
    }

A sample of the code that calls GetFunction.

 BlendEquationSeparate = Loader.GetFunction<glBlendEquationSeparate>("glBlendEquationSeparate");
 BlendEquationSeparatei = Loader.GetFunction<glBlendEquationSeparatei>("glBlendEquationSeparatei");
 BlendFunc = Loader.GetFunction<glBlendFunc>("glBlendFunc");
 BlendFunci = Loader.GetFunction<glBlendFunci>("glBlendFunci");
 BlendFuncSeparate = Loader.GetFunction<glBlendFuncSeparate>("glBlendFuncSeparate");
 BlendFuncSeparatei = Loader.GetFunction<glBlendFuncSeparatei>("glBlendFuncSeparatei");

A sample of the delegate code.

public delegate void glBlendEquationSeparate(BlendEquationMode modeRGB, BlendEquationMode modeAlpha);
public static glBlendEquationSeparate BlendEquationSeparate;
public delegate void glBlendEquationSeparatei(UInt32 buf, BlendEquationMode modeRGB, BlendEquationMode modeAlpha);
public static glBlendEquationSeparatei BlendEquationSeparatei;
public delegate void glBlendFunc(BlendingFactorSrc sfactor, BlendingFactorDest dfactor);
public static glBlendFunc BlendFunc;
public delegate void glBlendFunci(UInt32 buf, BlendingFactorSrc sfactor, BlendingFactorDest dfactor);
public static glBlendFunci BlendFunci;
public delegate void glBlendFuncSeparate(BlendingFactorSrc srcRGB, BlendingFactorDest dstRGB, BlendingFactorSrc srcAlpha, BlendingFactorDest dstAlpha);
public static glBlendFuncSeparate BlendFuncSeparate;
public delegate void glBlendFuncSeparatei(UInt32 buf, BlendingFactorSrc srcRGB, BlendingFactorDest dstRGB, BlendingFactorSrc srcAlpha, BlendingFactorDest dstAlpha);
public static glBlendFuncSeparatei BlendFuncSeparatei;

The DllImports I am using

[DllImport("kernel32")]
public static extern IntPtr LoadLibrary(string fileName);

[DllImport("kernel32")]
public static extern IntPtr GetProcAddress(IntPtr module, string procName);

[DllImport("opengl32.dll", EntryPoint = "wglGetProcAddress", ExactSpelling = true)]
public static extern IntPtr wglGetProcAddress(string lpszProc);

All the enums are pretty standard, and need no context. I load the library like usual: LoadLibrary(opengl32.dll);. Can anyone explain to me where I am going wrong?

  • 3
    May not be a random coincidence: `glBlendFunc` is one of the functions that would go through the `GetProcAddress` code path (legacy functions are exported by opengl32.dll directly). One reason that `GetProcAddress` could break is using a bad dllimport for it, could you show that? (notably, the top hit on google for "`GetProcAddress` C#" prominently features an incorrect way to dllimport it) – harold Dec 30 '21 at 04:42
  • Another way that `GetProcAddress` could break is passing it the wrong handle, so could you show that code too (you showed some `LoadLibrary` call here, but that cannot be real code, so I cannot be sure that the actual code does the right thing) – harold Dec 30 '21 at 04:47
  • @harold I edited the question to include the dllimports. – Wannabe Programmer Dec 30 '21 at 15:53
  • OK those look fine. What about the `Handle` then, what handle do you pass in? – harold Dec 30 '21 at 15:57
  • @harold I pass in the handle that LoadLibrary returns, from "opengl32.dll". – Wannabe Programmer Dec 30 '21 at 18:25
  • I have been staring at this code for hours now, and there is nothing wrong with it? I don't understand what I did wrong. I am even comparing it to other people's wrappers, and it is exactly how it should be? – Wannabe Programmer Dec 30 '21 at 20:07
  • @harold please don't abandon me here buddy – Wannabe Programmer Jan 02 '22 at 16:08
  • I'm kinda out of ideas here though.. – harold Jan 02 '22 at 18:15
  • @harold I just tried making the loading static and at the beginning of the game's execution, and it now works? What I don't get is that you can't load OpenGL without a context already existing, yet it works when the application just opens. I don't understand how that could even be remotely possible. – Wannabe Programmer Jan 02 '22 at 19:15
  • That's the kind of thing that's unofficial, but often works.. What's more mysterious is why the other approach didn't work. Do any of the values look weird in the debugger at the moment when `GetFunction` fails? – harold Jan 02 '22 at 19:57
  • @harold Everything looks perfectly fine in the debugger. It just bombs when it reaches glBlendFunc, and gives no information as to why. OpenGL's glGetError gives no information either. – Wannabe Programmer Jan 02 '22 at 21:49

1 Answers1

0

I have found a somewhat strange solution. If I move the code to a static constructor so that it runs at the beginning of the program, it suddenly works. I have no idea why my first approach didn't work.