C# Zugriff auf C-DLL bei x86 & x64

  • C#
  • .NET (FX) 1.0–2.0

Es gibt 14 Antworten in diesem Thema. Der letzte Beitrag () ist von Radinator.

    C# Zugriff auf C-DLL bei x86 & x64

    Hey,

    Ich bin gerade am experimentieren nachdem ich den Thread von @RodFromGermany gelesen habe : Austausch von Daten zwischen einer VB.NET-exe und einer C-DLL, 32 und 64 Bit
    Ich habe eine simple C-DLL die zwei integer miteinander verrechnet und ein Ergebnis zurückgibt.
    Dieses wird von meiner C# App erhalten und kann angezeigt werden.
    Es gibt jedoch eine Exception :

    Quellcode

    1. Additional information: An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)


    Ich denke das ganze ist ein Architektur (x86/x64) Problem..
    Was kann ich machen das der Zugriff auf die C-DLL auf jedem Windows System, egal ob x86 oder x64 Architektur ohne Probleme funktioniert.
    Was mache ich falsche, bitte um Hilfe!

    Project Src:
    NativeDLL.rar
    C# Developer
    Learning C++

    mrMo schrieb:

    AnyCPU
    ist da suboptimal.
    Besser ist es, x86 sowie x64 zu implementieren und AnyCPU explizit rauszuschmeißen.
    @Rikudo Lade mal die Projektdateien runter und übernimm sie. Ich weiß jetzt nicht genau, aber es kann sein, dass die C-DLL dort nur für 32 Bit eingerichtet ist.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    AnyCPU ist super geeignet, man muss die ganze Sache nur anders angehen.
    Anstelle von DllImport verwendet man dann nämlich folgendes:
    Auf Windows: LoadLibrary und GetProcAddress
    Auf *nix: dlopen und dlsym

    Dann entscheidest du zur Laufzeit, ob du 32Bit oder 64Bit laden musst und rufst enstprechend LoadLibrary auf. DllImport macht das auch nicht anders.
    Mittels GetProcAddres bekommst du dann einen Funktionspointer auf die jeweiligen Funktionen, das ganze kann man mit einem eigenen Attribut machen, welches du mittels reflection zur Laufzeit einmalig durchgehst um alle Funktionspointer zu laden.

    Gibt dir auch zusätzlich den Vorteil nach mehreren Möglichen Namen der Library oder unterschiedlichen Installationsorten zu suchen, was mittels DllImport nicht möglich ist(sucht nur in system32/PATH und eigenem Ordner - was LoadLibrary von sich aus eben auch macht)
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Es geht auch prima mit DllImport und AnyCPU.
    Dafür braucht man allerdings sowohl eine 32Bit alsauch eine 64Bit Version der nativen DLL. In C# importiert man dann die Funktionen aus beiden und entscheidet zur Laufzeit (z.B. mit Environment.Is64BitProcess), welche der importierten Funktionen man aufruft. Das klappt, weil die native DLL tatsächlich erst beim ersten Aufruf der Funktion geladen wird.
    Wer ein Beispiel sehen will, ich hab das in meinem aktuellen Projekt mit Zlib gemacht:
    github.com/Artentus/ModMyFacto…Crc32ChecksumGenerator.cs

    jvbsl schrieb:

    AnyCPU ist super geeignet, man muss die ganze Sache nur anders angehen.
    Anstelle von DllImport verwendet man dann nämlich folgendes:
    Auf Windows: LoadLibrary und GetProcAddress
    Auf *nix: dlopen und dlsym

    Dann entscheidest du zur Laufzeit, ob du 32Bit oder 64Bit laden musst und rufst enstprechend LoadLibrary auf. DllImport macht das auch nicht anders.
    Mittels GetProcAddres bekommst du dann einen Funktionspointer auf die jeweiligen Funktionen, das ganze kann man mit einem eigenen Attribut machen, welches du mittels reflection zur Laufzeit einmalig durchgehst um alle Funktionspointer zu laden.

    Gibt dir auch zusätzlich den Vorteil nach mehreren Möglichen Namen der Library oder unterschiedlichen Installationsorten zu suchen, was mittels DllImport nicht möglich ist(sucht nur in system32/PATH und eigenem Ordner - was LoadLibrary von sich aus eben auch macht)


    Die unterscheidung dann in etwa so:

    C#-Quellcode

    1. if(IntPtr.Size == 8)
    2. Loadx64();
    3. else
    4. Loadx86();


    oder gibt mir das nur aus auf welcher architektur das ssystem läuft?
    weil relevant ist ja ehr ob der prozess als 32bit Prozess oder als 64bit Prozess geladen wird.

    Aber okay, LoadLibrary ist also the way to go?

    @Artentus : Environment.Is64BitProcess ist nur seit FW 4.0 verfügbar..
    AnyCPU sagt doch nur das die Anwendung als x64 ausgeführt ist wenn es ein x64 system ist oder?
    Und du meisnt ich soll doch DllImport statt LoadLibrary nehmen? Jetzt bin ich verwirrt ._.
    C# Developer
    Learning C++

    Rikudo schrieb:

    Die unterscheidung dann in etwa so:

    VB.NET-Quellcode

    1. If Environment.Is64BitProcess Then
    2. Else
    3. End If
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Das kann ich nur bestätigen. Mit

    LoadLibrary
    GetProcAddress
    FreeLibrary

    und mit dem UnmanagedFunctionPointerAttribute für das Delegate funktioniert das mit AnyCPU. Die Unterscheidung jedoch zwischen einer 32Bit oder 64Bit-Dll bei Eigenbau muss trozdem gemacht werden.

    Freundliche Grüsse

    exc-jdbi

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „exc-jdbi“ ()

    exc-jdbi schrieb:

    Das kann ich nur bestätigen. Mit

    LoadLibrary
    GetProcAddress
    FreeLibrary

    und mit dem UnmanagedFunctionPointerAttribute funktioniert das mit AnyCPU. Die Unterscheidung jedoch zwischen einer 32Bit oder 64Bit-Dll bei Eigenbau muss trozdem gemacht werden.

    Freundliche Grüsse

    exc-jdbi

    Das heißt ich komme nicht drum herum meine native DLL einmal als x64 und einmal als x86 zu kompilieren? :x
    C# Developer
    Learning C++
    Eine

    Rikudo schrieb:

    native DLL
    hat nicht das Attribut AnyCPU, das haben nur .NET-Assemblies.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Du kommst um das kompilieren der nativen DLL nur mittels einer ABI, auf welche du von einem 32 Bit Prozess aus Zugreifst.
    Z.B. COM. COM hat quasi einen 32 Bit und einen 64 Bit Prozess am laufen und jenachdem auf was für eine Assembly du zugreifen möchtest geschieht dies mittels des jeweilig passendem Prozess.
    Aus deiner Anwendung dann greifst du über die COM-Schnittstelle zu, welche mit einem der beiden Prozesse kommuniziert. Ich weiß zwar nicht wie genau diese Kommunikation funktioniert, aber es wird irgendetwas Richtung ICP(Pipes/SharedMemory)/Kernel calls sein.
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---

    Rikudo schrieb:

    Environment.Is64BitProcess ist nur seit FW 4.0 verfügbar..

    Es geht genauso auch mit der IntPtr.Size-Methode, die du oben selbst gepostet hast.

    Rikudo schrieb:

    Und du meisnt ich soll doch DllImport statt LoadLibrary nehmen? Jetzt bin ich verwirrt ._.

    Du kannst auch LoadLibrary verwenden, es ist mit DllImport mmn nur extrem viel einfacher.
    Kannst du uns evtl den Code für CalcSecret zukommen lassen? - Edit: Hab den Ordner nicht gesehen *doh*

    Edit: Ich hab mal das C-Projekt auf Plattform Win32 und die C# Anwendung auf x86 gestellt, und siehe da: Es funzt!
    In general (across programming languages), a pointer is a number that represents a physical location in memory. A nullpointer is (almost always) one that points to 0, and is widely recognized as "not pointing to anything". Since systems have different amounts of supported memory, it doesn't always take the same number of bytes to hold that number, so we call a "native size integer" one that can hold a pointer on any particular system. - Sam Harwell

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Radinator“ ()