问题
I'm working on a C# utility library for OpenGL at the moment. For cross platform window management I use GLFW and I got functions like glfwCreateWindow or glfwMakeContextCurrent loaded successfully with DllImport.
Now I want to use OpenGL and since I've mostly worked with GLEW in the past I decided to use it for my C# project as well.
So I tried to use DllImport for glewInit and that worked. But when I try to do the same thing for OpenGL functions such as glClear I get an error saying that it can't find the function. I looked up the exact function name and parameters in the glew header file, but I think I did that correctly. Also I am creating an OpenGL context and calling glewInit before using it.
Here's the function declaration:
GLAPI void GLAPIENTRY glClear (GLbitfield mask);
And this is how I load the function from my C# program:
[DllImport("GLEW dll path here")]
internal static extern void glClear(int mask);
Is it because the function pointers get loaded at runtime? Or am I doing something wrong loading the function?
I would appreciate any help / comments / hints. If you need more code I can edit the post.
I'm quite new to stackoverflow, so please let me know if I'm doing something incorrectly.
回答1:
For glClear
specifically, the following should be enough:
[DllImport("opengl32.dll")]
public static extern void glClear(uint clearMask);
In Windows GL functions are defined in opengl32.dll
and should be loaded from there. There is a caveat though: opengl32.dll
is only compatible with very basic OpenGL version (1.1? not sure), and does not contain any fancy functions available in more recent OpenGL versions (the context created by default may very well be v. 4.x compatible, but you simply don't have proper pointers to newer functions).
In C or C++, you load those function pointers with wglGetProcAddress, but it gets very unwieldy very fast, that's where libraries like Glew come in: they contain all boilerplate to declare and load those newer GL functions. Unfortunately, it's a bit less useful for the C#: you still need to declare method you are going to call there, and Glew will not help you with it in any way.
So, suppose you want to call glCompileShader
. For that you need to be able to call wglGetProcAddress
first:
[DllImport("opengl32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern IntPtr wglGetProcAddress(string functionName);
(you also need to make sure you call it on the thread that has GL context set as current after the context was set as current (that is, after wglMakeCurrent
was called), otherwise the call will fail)
Then, declare delegate:
delegate void GlCompileShaderDelegate(uint shader);
Then, load function address:
IntPtr glCompileShaderPtr = GL.wglGetProcAddress("glCompileShader");
if (glCompileShaderPtr == IntPtr.Zero)
{
// load failed
}
Then, convert the address to delegate:
GlCompileShaderDelegate glCompileShader = Marshal.GetDelegateForFunctionPointer<GlCompileShaderDelegate>(glCompileShaderPtr);
Now you can call glCompileShader
from your C# code. Rinse and repeat for every single GL function you want to call (except those that are readily available in opengl32.dll
of course), and don't mess up character encoding if you pass or receive strings from the OpenGL functions.
Now that you know how to do that, save yourself time and find a library that does it for you.
回答2:
OK, so the way handled this problem is by no means ideal and I'll try to find a different solution.
For now I wrote a wrapper around GLFW and GLEW using C++, in which I use
extern "C" _declspec(dllexport)
to wrap everything I need. I link the libs statically so that I only have one dll in the end, and I can customize the dll's content to a higher degree. Also this allows me to continue using DllImport to load the functions instead of doing everything at runtime once the function pointers are loaded.
But as said, it's not the best thing to do, and I have to manually wrap every function I want to use. For now it should get the job done and I can work on the library itself in the meantime.
Just wanted to let anyone know who cares about it.
来源:https://stackoverflow.com/questions/47237555/calling-opengl-functions-in-c-sharp-using-dllimport