繁体   English   中英

尝试通过互操作将C ++转换为C#

[英]Attempting to convert C++ into C# with interop

我有一个程序可以在C ++中调用EGL。 我想在C#中进行相同的调用,但是C#中似乎没有一个等效的概念。

当执行上下文输入C ++ EGL代码时,出现读/写访问被拒绝错误。

这是我要转换为C#的C ++程序中的代码:

PropertySet^ surfaceCreationProperties = ref new PropertySet();
surfaceCreationProperties->Insert(ref new String(EGLNativeWindowTypeProperty), somethingOtherThanAWindow);

mEglSurface = eglCreateWindowSurface(mEglDisplay, config, reinterpret_cast<IInspectable*>(surfaceCreationProperties), surfaceAttributes));

我有一个C#类,它将C#EGL调用转换为C ++调用。 我相信C ++是不受管理的,尽管我不知道该如何确定。

C#类如下所示:

public static IntPtr CreateWindowSurface(IntPtr dpy, IntPtr config, IntPtr win, int[] attrib_list)
{
    IntPtr retValue;

    unsafe {
        fixed (int* p_attrib_list = attrib_list)
        {
            retValue = Delegates.peglCreateWindowSurface(dpy, config, win, p_attrib_list);
        }
    }
    return (retValue);
}

可以在这里查看更多该代码: https : //github.com/luca-piccioni/OpenGL.Net/blob/master/OpenGL.Net/Egl.VERSION_1_0.cs#L751

您可能会注意到此方法IntPtr winIntPtr win -这就是我传递PropertySet 通常,我相信这将是System.Windows.Forms.Control ,但是会在C ++ EGL代码中进行一些检查以查看它是否为PropertySet

被调用的C ++方法是这样的:

EGLSurface EGLAPIENTRY CreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)

可以在这里看到更多信息: https : //github.com/Microsoft/angle/blob/ms-holographic-experimental/src/libGLESv2/entry_points_egl.cpp#L241

如您所见,C ++方法期望使用EGLNativeWindowType。 我不确定IInspectable和PropertSet之间的关系是什么-可以强制转换似乎很奇怪。

EGLNativeWindowType具有以下类型定义:

typedef HWND EGLNativeWindowType;

这意味着它必须是某种窗口句柄。 我不明白PropertySet如何成为窗口句柄。

我怀疑主要问题在于选择正确类型的对象以传递给C#EGL实现。 PropertySet似乎是正确的选择,但是reinterpret_cast确实让我失望了。

谁能引导我完成这个任务?

通常我相信这将是System.Windows.Forms.Control ...

这是一个痛苦的错误假设。 要理解打字,需要写三本书,这在SO答案中很难做到。 如果您实际上打算从Winforms应用程序执行此操作,然后立即停止,那将永远无法进行。

OpenGL使用非常宽松的类型,其api函数的参数只不过是void* (原始指针)而已。 这使其非常灵活,但是指针实际指向的内容非常重要。 如果客户端程序和视频适配器接口在丝毫不同意,则您的程序将构建得很好,但将在运行时崩溃并以完全无法诊断的方式刻录。 结果是Microsoft放弃OpenGL并决定创建自己的DirectX的主要原因。

它也使用指针,但是它们是更聪明的一种,它们在运行时支持类型发现。 它们是IUnknown指针,其QueryInterface()方法允许找出对象是否支持特定的预期接口。 您在这里看到的风格与指针完全相同, IInspectable是一个比IUnknown稍微聪明的版本,并且所有WinRT类都实现了基本接口。 你真的传递一个IInspectable *自认为是角度端口所期待的。

通常,您期望可以只传递一个ICoreWindow接口指针并完成操作,这就是窗口的WinRT接口。 但是,渲染器不仅需要ICoreWindow,还需要更多信息。 不确定原因,我认为这与WinRT中的分辨率独立性有关。 它还需要知道表面的大小和比例因子。

问题是,OpenGL无法传递该信息。 因此,Microsoft程序员使用了一个非常棘手的技巧,而不是添加一个传递该信息的函数,而是使用了IMap<String^, IInspectable*>指针来使他不具有传递任何IInspectable *的能力。 基本上是一个属性包,ANGLE端口中的CoreWindowNativeWindow.cpp在其CoreWindowNativeWindow :: initialize()函数中再次从该包中挖掘属性。

PropertySet是C ++语言投影中的一个具体类,实现IMap<K, V> 请注意,它特定于C ++,在C#中,您应该使用Dictionary<string, IntPtr> CLR中内置的语言投影会自动将托管字典映射到本机IMap接口。

太高兴了,还有更多IntPtrs。 IInspectable *完全隐藏在您在C#中使用的语言投影中,这并不容易。 我98%的确定您可以使用Marshal.GetIUnknownForObject()获得有效的指针,即使它的味道不正确。 由于C ++代码做正确的事并使用QueryInterface :)您必须在之后调用Marshal.Release()进行清理,否则将导致内存泄漏。

请注意,您做错事有很强的色彩。 我想您是,Microsoft仅出于一个原因提供了ANGLE分支。 他们试图使公司轻松将其iOS游戏移植到WinRT / UWP。 Kinda必须为商店提供顾客喜欢的游戏。 ANGLE端口仅旨在从以ObjectiveC或C ++开头的代码(用于编写这些游戏的语言)中轻松使用。

他们本来可以使使用Java语言或C#等语言的库变得容易得多,但这并不是因为没有必要。 如果您有翻译的C ++代码度量英里是使用OpenGL到C#则是相当有可能你会好得多 ,当您使用DirectX代替。 这种类型的映射会遇到更多其他功能的麻烦,并且会对实验性的HoloLens端口感到厌倦。

我认为参数类型肯定是错误的。

对于完整的示例,您应该阅读https://github.com/luca-piccioni/OpenGL.Net/blob/master/OpenGL.Net/NativeDeviceContext.cs中的DeviceContext实现。 您还应该查看该代码的调用位置,以便获得初始化EGL所需的实际调用序列:-工厂方法: https//github.com/luca-piccioni/OpenGL.Net/blob/master/OpenGL.Net/ DeviceContextFactory.cs-控件集成: https : //github.com/luca-piccioni/OpenGL.Net/blob/master/OpenGL.Net/GlControl.cs

如您所见,该句柄是Control.Handle属性。 可能传递的实际值取决于实现EGL的当前操作系统,但是它应该是承载绘图结果的窗口(或控件)的句柄。


另外,您可以检查实际的EGL方法实现,并遵循参数用法直到真正的DirectX调用为止,就像我当时所做的那样。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM