使用DllImport在C#中调用OpenGL函数?

时间:2017-11-11 11:47:14

标签: c# opengl dllimport glew

我目前正在为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很新,所以如果我做错了,请告诉我。

2 个答案:

答案 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加载函数,而不是在加载函数指针后在运行时执行所有操作。

但是如上所述,这不是最好的事情,我必须手动包装我想要使用的每个功能。现在它应该完成工作,同时我可以在库本身上工作。

只是想让任何人知道谁在乎它。