2009-03-17 14 views
0

À la suite de mon recent question sur le débogage .NET Compact Framework, j'essaie actuellement d'utiliser OpenGL ES à partir d'un .NET Compact Framework et une application .NET Framework. J'utilise this wrapper, qui a été créé pour OpenGL ES et importe depuis libGLES_CM.dll. Pour faciliter le débogage, j'ai créé une application .NET Framework, recréé le projet d'importation pour OpenGL ES et EGL avec les mêmes fichiers (construction pour Desktop), créé des constantes pour les noms de DLL afin qu'ils puissent être importés de libGLESv2.dll et libEGL.dll sous Windows et libGLES_CM.dll sur CF. Les DLL proviennent du SDK PowerVR OpenGL ES Emulation (le périphérique cible possède un PowerVR SGX) et ne sont qu'un wrapper OpenGL ES autour de l'implémentation OpenGL réelle. Et voici le problème:DllImport avec différents points d'entrée (différentes DLL pour la même importation dans différents projets)

Dans la bibliothèque wrapper, les fonctions OpenGL sont dans deux classes statiques (gl et egl) et ont le nom habituel, mais sans le préfixe gl/egl, donc les appelant serait egl.GetDisplay() au lieu de egl.eglGetDisplay(). Ils sont importés comme ceci:

[DllImport(DllName, EntryPoint = "eglGetDisplay")] 
static extern IntPtr GetDisplay(EGLNativeDisplayType display_id); 

Cela fonctionne très bien sur le Compact Framework. Dans le projet de bureau, une EntryPointNotFoundException est lancée - car les fonctions sont nommées [email protected](remarque: le WMD attrape Alt-Gr + Q pour les blockquotes, qui est le symbole at sur les configurations de clavier allemand. selon Dependency Walker. J'ai réussi à obtenir le soulignement ajouté au nom de la fonction pour le projet de bureau, mais pas pour le projet CF, en définissant conditionnellement une chaîne à la chaîne vide ou "_" et en la concaténant ainsi que le nom du point d'entrée, donc ça ressemble à ceci:

[DllImport(DllName, EntryPoint = FunctionPrefix + "eglGetDisplay")] 

Pas de problème ici. Mais la fonction n'est toujours pas trouvée, car le @ 4 (qu'est-ce que c'est exactement?) Est manquant. Si j'ajoute le @ 4, cela fonctionne, mais puisque toutes les fonctions ont des valeurs différentes ici, je devais le faire à la main et probablement les chiffres ne seraient pas corrects pour la version CF. Voici la partie étrange:

Si je ne spécifie pas le point d'entrée et nomme la fonction comme il devrait être nommé, l'importation fonctionne bien! Maintenant, c'est moche à cause du double préfixe (nom de la classe statique et nom de la fonction), bien que je puisse contourner cela en ajoutant simplement un wrapper pour celui-ci. Comme je ne me fierai pas beaucoup à ces fonctions (il me faut seulement un moteur 2D assez simple), ce ne serait pas un problème, mais ça ne me semble pas juste. Pourquoi cela ne fonctionne-t-il pas lorsque vous spécifiez le point d'entrée?

Pourquoi cela ne fonctionne-t-il pas? Que puis-je faire pour que cela fonctionne comme il se doit?

Répondre

3

Si les API CF et de bureau ont des points d'entrée différents, vous devez travailler avec ceci. Cela signifie que vous avez besoin de différents DllImport définis. Il est plus facile d'avoir deux classes wrapper implémentant tous les noms internes (.NET), qui appellent leur importation, puis instancient la bonne au moment de l'exécution en fonction de la plate-forme. Ensuite, accédez aux API via l'interface commune.

Interface IGLImports { 
    IntPtr GetDisplay(EGLNativeDisplayType display_id); 
} 

static class CFRawImports { 
    [DllImport(DllName, EntryPoint = "eglGetDisplay")] 
    static extern IntPtr GetDisplay(EGLNativeDisplayType display_id); 
} 

static class DeskRawImports { 
    [DllImport(DllName, EntryPoint = "[email protected]")] 
    static extern IntPtr GetDisplay(EGLNativeDisplayType display_id); 
} 

class DesktopImports : IGLImports { 
    public IntPtr GetDisplay(EGLNativeDisplayType display_id) { 
    return DeskRawImports.GetDisplay(display_id); 
    } 
} 

class CFImports : IGLImports { 
    public IntPtr GetDisplay(EGLNativeDisplayType display_id) { 
    return CFRawImports.GetDisplay(display_id); 
    } 
} 

static class ImportLoader { 
    public static IGLImports GetImports() { 
    if (isCF) { 
     return new CFImports(); 
    } else { 
     return new DesktopImports(); 
    } 
    } 
} 

class MyApp { 
    private static IGLIMports gl = ImportLoader.GetImports(); 

    // In code use gl.GetDesktop(...) 

EDIT: L'interface et quatre classes devraient être creatable avec un peu de génération de code. Fichier d'entrée contenant le nom DesktopImport CFImport (peut-être ajouter des noms de DLL si ceux-ci varient). Ce serait une excuse pour apprendre le templating T4 VS ...

+0

J'espérais que ce serait plus facile. Dans ce cas, je pense que je préférerais les importer avec le bon nom et sans spécifier le point d'entrée, et ensuite mettre juste un emballage autour d'eux pour rendre le nom magnifique. – OregonGhost

+0

@your edit: Oui, un collègue a suggéré une solution similaire. Mais comme je l'ai déjà dit, je n'aurai pas besoin de tant de fonctions et je devrais quand même les envelopper dans ma propre petite bibliothèque (vous savez, avec des classes et des objets au lieu de fonctions flottantes) ... Nous verrons;) – OregonGhost

+0

Jamais entendu parler de T4 avant, regardé maintenant. Ça semble amusant! –

1

Un nom décoré est une chaîne créée par le compilateur lors de la compilation de la définition de la fonction ou du prototype. "@ 4" dans le nom signifie qu'il a une longueur totale de paramètre de 4 octets (un entier de 32 bits?).

Vous pouvez utiliser dumpbin.exe pour obtenir les noms décorés de vous .dll.

+0

Ensuite, je devrais encore les mettre quelque part dans le projet de wrapper. Ne m'attire pas :) – OregonGhost

+0

J'ai juste supervisé votre explication de la chose @ 4. Oui, c'est un int 32 bits dans ce cas. +1 pour cette explication, bien que cela ne m'aide pas vraiment;) – OregonGhost

+0

Merci, désolé si cela n'a pas beaucoup aidé. J'espère que vous n'aurez pas besoin d'envelopper trop de méthodes! :) – Groo

0

utilisation #define yourdllname_API extern « C » __declspec (dllexport) pour exposer les méthodes dans votre dll, ce qui évite la décoration de la fonction de cette façon vous obtenez ci-dessus mentionné habitude Excepción, par exemple :

DLL:

#ifdef DEPLOYHOOK_EXPORTS 
#define DEPLOYHOOK_API extern "C" __declspec(dllexport) 
#else 
#define DEPLOYHOOK_API __declspec(dllimport) 
#endif 

// This class is exported from the DeployHook.dll 

DEPLOYHOOK_API int nDeployHook; 


DEPLOYHOOK_API bool InstallHook(void); 
DEPLOYHOOK_API bool UnInstallHook(void); 

appel de projet/exe:

[DllImport("DeployHook.dll",EntryPoint = "InstallHook",CharSet = CharSet::Auto, SetLastError = true)] extern bool InstallHook(void); 

// EntryPointN otFoundException a évité

+0

Cela manque malheureusement le point, puisque je n'ai pas de contrôle sur les DLL importées. Merci pour votre contribution de toute façon. – OregonGhost