2009-03-17 9 views
0

Als Folge meiner recent question über .NET Compact Framework Debuggen, versuche ich derzeit, OpenGL ES von einem .NET Compact Framework und eine .NET Framework-Anwendung. Ich benutze this wrapper, die für OpenGL ES erstellt wurde und importiert von libGLES_CM.dll.DllImport mit verschiedenen Einstiegspunkten (verschiedene DLLs für den gleichen Import in verschiedenen Projekten)

Um das Debuggen zu erleichtern, erstellte ich eine .NET Framework-Anwendung, erstellte das Importprojekt für OpenGL ES und EGL mit denselben Dateien (nur für Desktop-Framework erstellen), erstellte Konstanten für die DLL-Namen, aus denen sie importieren libGLESv2.dll und libEGL.dll unter Windows und von libGLES_CM.dll auf CF. Die DLLs stammen vom PowerVR OpenGL ES Emulation SDK (das Zielgerät hat einen PowerVR SGX) und sind nur ein OpenGL ES-Wrapper um die echte OpenGL-Implementierung. Und hier kommt das Problem:

In der Wrapper-Bibliothek sind die OpenGL-Funktionen in zwei statischen Klassen (gl und egl) und haben den üblichen Namen, aber ohne das gl/egl-Präfix, so egl.GetDisplay() statt egl.eglGetDisplay(). Sie werden folgendermaßen importiert:

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

Dies funktioniert gut auf dem Compact Framework. Im Desktop-Projekt wird eine EntryPointNotFoundException ausgelöst - weil die Funktionen wie benannt sind (Randnotiz: die WMD fängt Alt-Gr + Q für Blockquotes, das ist das At-Symbol auf deutschen Tastaturlayouts. Ich musste dieses einfügen.) nach Dependency Walker.

Ich habe es geschafft, den Unterstrich zum Funktionsnamen für das Desktop-Projekt hinzuzufügen, aber nicht für den CF, indem ich eine Zeichenkette konstant auf leere Zeichenkette oder "_" setze und sie mit dem Einstiegspunktnamen verkette, so sieht es so aus:

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

Kein Problem hier. Aber die Funktion wird immer noch nicht gefunden, weil das @ 4 (was genau ist das?) Fehlt. Wenn ich das @ 4 hinzufüge, funktioniert das, aber da alle Funktionen hier unterschiedliche Werte haben, musste ich dies per Hand machen und wahrscheinlich wären die Zahlen für die CF-Version nicht korrekt. Hier kommt der seltsame Teil:

Wenn ich nur den Einstiegspunkt nicht angeben und stattdessen die Funktion benennen, wie es benannt werden soll, funktioniert der Import gut! Nun ist das hässlich wegen des Doppelpräfixes (Name der statischen Klasse und Funktionsname), obwohl ich das umgehen könnte, indem ich einfach einen Wrapper für diesen hinzufüge. Da ich mich nicht stark auf diese Funktionen verlassen werde (brauche nur eine ziemlich einfache 2D-Engine), wäre das kein Problem, aber es fühlt sich einfach nicht richtig an.

Warum funktioniert es nicht, wenn der Einstiegspunkt angegeben wird? Was kann ich tun, damit es so funktioniert, wie es sollte?

Antwort

3

Wenn die CF- und Desktop-APIs unterschiedliche Einstiegspunkte haben, müssen Sie damit arbeiten. Es bedeutet, dass Sie verschiedene DllImports definiert haben.

Am einfachsten ist es, zwei Wrapper-Klassen zu haben, die alle internen (.NET) Namen implementieren, die ihren Import aufrufen, und dann je nach Plattform den richtigen zur Laufzeit instanziieren. Greifen Sie dann über die allgemeine Schnittstelle auf die APIs zu.

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: Die Schnittstelle und vier Klassen sollten mit einer kleinen Code-Generierung erstellbar sein. Eingabedatei, die den Namen DesktopImport CFImport enthält (eventuell Hinzufügen von DLL-Namen, falls diese unterschiedlich sind). Würde ein Vorwand sein VS des T4 Templat ...

+0

Ich hoffte, es wäre einfacher. In diesem Fall denke ich, dass ich es vorziehe, sie mit dem richtigen Namen und ohne Angabe des Einstiegspunktes zu importieren, und dann einfach einen Wrapper um sie zu legen, um den Namen schön zu machen. – OregonGhost

+0

@your edit: Ja, ein Kollege schlug eine ähnliche Lösung vor. Aber wie ich bereits sagte, brauche ich nicht so viele Funktionen und werde sie sowieso in meine eigene kleine Bibliothek einpacken müssen (Sie wissen, mit Klassen und Objekten anstelle von freischwebenden Funktionen) ... Wir werden sehen;) – OregonGhost

+0

Noch nie von T4 gehört, habe es jetzt nachgeschlagen. Sieht lustig aus! –

1

Ein dekorierter Name ist eine Zeichenfolge, die vom Compiler während der Kompilierung der Funktionsdefinition oder des Prototyps erstellt wurde. "@ 4" im Namen bedeutet, dass es insgesamt Parameterlänge von 4 Bytes (eine 32-Bit-Ganzzahl?) Hat.

Sie können dumpbin.exe verwenden, um die dekorierten Namen von Ihnen .dll zu erhalten.

+0

Dann müsste ich sie noch irgendwo in das Wrapper-Projekt setzen. Appelliert mich nicht :) – OregonGhost

+0

Ich habe nur Ihre Erklärung der @ 4 Sache überwacht. Ja, in diesem Fall ist es ein 32-Bit-Int. +1 für diese Erklärung, obwohl es mir nicht wirklich hilft;) – OregonGhost

+0

Danke, tut mir leid, wenn es nicht viel geholfen hat. Ich hoffe, Sie müssen nicht zu viele Methoden einpacken! :) – Groo

0

Verwendung #define yourdllname_API extern „C“ __declspec (dllexport) zu belichten Methoden in der DLL, die Vermeidung Funktion Dekoration, die Art und Weise Sie nicht oben erhalten erwähnt Excepcion, Beispiel zu lernen :

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); 

Aufruf Projekt/exe:

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

// EntryPointN otFoundException vermieden

+0

Das fehlt leider der Punkt, da ich die importierten DLLs nicht kontrollieren kann. Danke für deine Eingabe trotzdem. – OregonGhost