簡體   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