我目前正在为OpenGL的C#实用程序库工作。 对于跨平台窗口管理,我使用GLFW,我使用DllImport成功加载了glfwCreateWindow或glfwMakeContextCurrent等函数。
现在我想使用OpenGL,因为我过去主要使用GLEW,所以我决定将它用于我的C#项目。
所以我尝试将dllImport用于glewInit并且这很有用。 但是当我尝试为像glClear这样的OpenGL函数做同样的事情时,我得到一个错误,说它无法找到该函数。 我在glew头文件中查找了确切的函数名称和参数,但我认为我做得正确。 我也在创建一个OpenGL上下文并在使用之前调用glewInit。
这是函数声明:
GLAPI void GLAPIENTRY glClear (GLbitfield mask);
这就是我从C#程序加载函数的方法:
[DllImport("GLEW dll path here")]
internal static extern void glClear(int mask);
是因为函数指针在运行时加载了吗? 或者我在加载函数时做错了什么?
我将不胜感激任何帮助/评论/提示。 如果您需要更多代码,我可以编辑帖子。
我对stackoverflow很新,所以如果我做错了,请告诉我。
答案 0 :(得分:3)
具体来说,对于glClear
,以下内容应该足够了:
[DllImport("opengl32.dll")]
public static extern void glClear(uint clearMask);
在Windows GL中,函数在opengl32.dll
中定义,应该从那里加载。但有一点需要注意:opengl32.dll
只与非常基本的OpenGL版本兼容(1.1?不确定),并且不包含更新的OpenGL版本中可用的任何花哨功能(默认情况下创建的上下文很可能是v .4.x兼容,但你根本没有适当的指针指向更新的功能。)
在C或C ++中,您使用wglGetProcAddress
加载这些函数指针,但它非常笨拙,这就像Glew这样的库进来了:它们包含所有声明和加载那些较新GL函数的样板。不幸的是,它对C#来说有点用处:你仍然需要声明你打算在那里打电话的方法,而Glew不会以任何方式帮助你。
所以,假设您想要致电glCompileShader
。为此,您需要先调用wglGetProcAddress
:
[DllImport("opengl32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern IntPtr wglGetProcAddress(string functionName);
(您还需要确保在上下文设置为当前(即调用wglMakeCurrent
之后)将GL上下文设置为当前的线程上调用它,否则通话将失败)
然后,声明委托:
delegate void GlCompileShaderDelegate(uint shader);
然后,加载功能地址:
IntPtr glCompileShaderPtr = GL.wglGetProcAddress("glCompileShader");
if (glCompileShaderPtr == IntPtr.Zero)
{
// load failed
}
然后,将地址转换为委托:
GlCompileShaderDelegate glCompileShader = Marshal.GetDelegateForFunctionPointer<GlCompileShaderDelegate>(glCompileShaderPtr);
现在您可以从C#代码中调用glCompileShader
。冲洗并重复每个要调用的单个GL函数(当然opengl32.dll
中可以使用的函数除外),如果从OpenGL函数传递或接收字符串,则不要弄乱字符编码。
现在您已经知道如何做到这一点,节省时间并找到适合您的库。
答案 1 :(得分:0)
好的,所以处理这个问题的方法绝不是理想的,我会尝试找到不同的解决方案。
现在我用C ++写了一个GLFW和GLEW的包装器,我用它来
extern "C" _declspec(dllexport)
包装我需要的一切。 我静态链接libs,这样我最终只有一个dll,我可以更高程度地自定义dll的内容。 这也允许我继续使用DllImport加载函数,而不是在加载函数指针后在运行时执行所有操作。
但是如上所述,这不是最好的事情,我必须手动包装我想要使用的每个功能。现在它应该完成工作,同时我可以在库本身上工作。
只是想让任何人知道谁在乎它。