Tenter de convertir C ++ en C # avec interop

J’ai un programme qui appelle EGL en C ++. Je souhaite effectuer le même appel en C #, mais il ne semble pas exister de concept équivalent en C #.

Une erreur d’access en lecture / écriture est refusée lorsque le contexte d’exécution entre dans le code C ++ EGL.

C’est le code du programme C ++ que j’essaie de convertir en C #:

PropertySet^ surfaceCreationProperties = ref new PropertySet(); surfaceCreationProperties->Insert(ref new Ssortingng(EGLNativeWindowTypeProperty), somethingOtherThanAWindow); mEglSurface = eglCreateWindowSurface(mEglDisplay, config, reinterpret_cast(surfaceCreationProperties), surfaceAtsortingbutes)); 

J’ai une classe C # qui convertit les appels C # EGL en appels C ++. Je crois que le C ++ n’est pas géré, bien que je ne sache pas comment vous le dire avec certitude.

La classe C # ressemble à ceci:

 public static IntPtr CreateWindowSurface(IntPtr dpy, IntPtr config, IntPtr win, int[] atsortingb_list) { IntPtr retValue; unsafe { fixed (int* p_atsortingb_list = atsortingb_list) { retValue = Delegates.peglCreateWindowSurface(dpy, config, win, p_atsortingb_list); } } return (retValue); } 

Plus de ce code peut être vu ici: https://github.com/luca-piccioni/OpenGL.Net/blob/master/OpenGL.Net/Egl.VERSION_1_0.cs#L751

Vous remarquerez peut-être que cette méthode a un IntPtr win – c’est là que je passe le PropertySet . En règle générale, je pense qu’il s’agirait d’un System.Windows.Forms.Control , mais une vérification est effectuée dans le code C ++ EGL pour voir si c’est le cas ou s’il s’agit d’un PropertySet .

La méthode C ++ appelée est la suivante:

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

Plus peut être vu ici: https://github.com/Microsoft/angle/blob/ms-holographic-experimental/src/libGLESv2/entry_points_egl.cpp#L241

Comme vous pouvez le constater, la méthode C ++ attend un EGLNativeWindowType. Je ne suis pas tout à fait sûr de la relation entre cela entre un IInsableable et un PropertSet – il semble étrange que cela puisse être jeté.

EGLNativeWindowType a la définition de type suivante:

 typedef HWND EGLNativeWindowType; 

Ce qui implique qu’il doit s’agir d’une sorte de poignée de fenêtre. Je ne comprends pas comment un PropertySet pourrait être un handle de fenêtre.

Je soupçonne que le problème principal concerne le choix du type d’object correct à transmettre à l’implémentation C # EGL. PropertySet semble être le bon choix, mais le reinterpret_cast me met vraiment au dépourvu.

Quelqu’un peut-il me guider à travers cela?

En règle générale, je pense que ce serait un System.Windows.Forms.Control …

C’est une hypothèse douloureusement erronée. Pour donner un sens à la frappe, il faut écrire trois livres, ce qui est difficile à faire avec une réponse SO. Si vous avez réellement l’intention de faire cela à partir d’une application Winforms, arrêtez-vous maintenant, cela ne fonctionnera jamais.

OpenGL utilise un typage très souple, les arguments de leurs fonctions api ne sont rien de plus que void* , un pointeur brut. Ce qui le rend très flexible mais il est vraiment important que le pointeur indique réellement. Si le programme client et l’interface de la carte graphique ne sont pas du même avis, votre programme se formera correctement, mais se plantera et se gravera de façon totalement indiagnostique au moment de l’exécution. Une des principales raisons pour lesquelles Microsoft a abandonné OpenGL et décidé de créer le leur, c’est DirectX.

Lesquels utilisent également des pointeurs, mais ils sont plus intelligents: ils prennent en charge la découverte de type au moment de l’exécution. Ce sont des pointeurs IUnknown , sa méthode QueryInterface () permet de savoir si un object prend en charge une interface spécifique attendue. La saveur que vous voyez utilisée ici est exactement du même type de pointeur. IInspectable est une version légèrement plus intelligente que IUnknown et l’interface de base implémentée par toutes les classes WinRT. Vous devez vraiment passer un non-respect *, car c’est ce que le port ANGLE attend.

Vous vous attendriez généralement à pouvoir simplement passer un pointeur d’interface ICoreWindow et à en ICoreWindow , c’est l’interface WinRT d’une fenêtre. Le moteur de rendu nécessite cependant plus d’informations que le ICoreWindow. Je ne sais pas trop pourquoi, je pense que cela a quelque chose à voir avec la résolution Independence dans WinRT. Il doit également connaître la taille de la surface et le facteur d’échelle.

Le problème, c’est qu’OpenGL n’a pas le moyen de transmettre cette information. Le programmeur de Microsoft a donc utilisé un hack très hokey, au lieu d’ append une fonction pour transmettre cette information, il a utilisé la possibilité de transmettre tout type de IIspectable *, mais un IMap . Fondamentalement, un sac de propriétés, CoreWindowNativeWindow.cpp dans le port ANGLE, extrait à nouveau les propriétés du sac dans sa fonction CoreWindowNativeWindow :: initialize ().

PropertySet est une classe concrète de la projection en langage C ++ qui implémente IMap . Notez qu’il est spécifique au C ++. En C #, vous utiliseriez plutôt un Dictionary . La projection de langue intégrée au CLR mappe automatiquement un dictionnaire géré à l’interface IMap native.

Oh joie, plus de IntPtrs. Inspectable * est complètement caché dans la projection de langage que vous utilisez en C #, cela ne facilite pas les choses. Je suis sûr à 98% que vous pouvez utiliser Marshal.GetIUnknownForObject () pour obtenir un pointeur qui fonctionne, même si sa saveur est fausse. Étant donné que le code C ++ agit correctement et utilise QueryInterface 🙂 Vous devez appeler Marshal.Release () par la suite pour nettoyer, faute de quoi, une fuite de mémoire risque de se produire.

Notez qu’il existe de fortes nuances de vous faire la mauvaise chose. Je pense que vous êtes, Microsoft fourni cette fourche ANGLE seulement pour une raison. Ils ont essayé d’aider les entresockets à transférer facilement leur jeu iOS sur WinRT / UWP. Un peu nécessaire pour remplir le magasin avec le genre de jeux que les clients aiment. Le port ANGLE n’a été conçu que pour être facile à utiliser à partir d’un code démarrant en ObjectiveC ou C ++, le type de langage utilisé pour écrire ces jeux.

Ils auraient pu beaucoup plus facilement utiliser la bibliothèque à partir de langages comme Javascript ou C #, mais ce n’était pas le cas, car ce n’était pas nécessaire. Si vous devez traduire un kilomètre mésortingque de code C ++ qui utilise OpenGL en C #, il est fort probable que vous feriez beaucoup mieux si vous utilisez DirectX à la place. Attendez-vous à plus de problèmes de ce type avec d’autres fonctions et soyez fatigué d’un port expérimental HoloLens.

Je pense que le type de paramètre est définitivement faux.

Pour un exemple complet, vous devriez lire l’implémentation DeviceContext dans https://github.com/luca-piccioni/OpenGL.Net/blob/master/OpenGL.Net/NativeDeviceContext.cs . Vous devriez également voir où ce code est appelé afin d’obtenir la séquence d’appels nécessaire pour initialiser EGL: – méthode d’usine: https://github.com/luca-piccioni/OpenGL.Net/blob/master/OpenGL.Net/ DeviceContextFactory.cs – Intégration du contrôle: https://github.com/luca-piccioni/OpenGL.Net/blob/master/OpenGL.Net/GlControl.cs

Comme vous pouvez le constater, le descripteur est la propriété Control.Handle. La valeur réelle à transmettre dépend probablement de l’OS actuel implémentant EGL, mais il doit s’agir d’un descripteur de la fenêtre (ou du contrôle) hébergeant les résultats du dessin.


Vous pouvez également vérifier l’implémentation réelle de la méthode EGL et suivre l’utilisation des parameters jusqu’à l’appel DirectX, ce que je venais de faire à ce moment-là.