2017-01-03 1 views
0

Ich versuche, eine C++ DLL aus meinem C# -Programm zu entladen und dann neu zu laden und ihre Funktionen zu verwenden. für das Entladen Teil benutzte ich diese Antwort: Unload a DLL loaded using DllImportC# Pinvoke und Neuladen einer DLL

Um es neu zu laden ich die Funktion Loadlibrary verwendet. Dies ist mein Code:

using System; 
using System.Runtime.InteropServices; 

namespace ConsoleApplication1 
{ 
    internal class Program 
    { 
     [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Ansi)] 
     private static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)]string lpFileName); 

     [DllImport("kernel32.dll", SetLastError = true)] 
     [return: MarshalAs(UnmanagedType.Bool)] 
     private static extern bool FreeLibrary(IntPtr hModule); 

     [DllImport("TestLibrary.dll", SetLastError = true)] 
     private static extern int GetValue(); 

     private static void Main(string[] args) 
     { 
      int val = GetValue(); 
      IntPtr p2 = LoadLibrary("TestLibrary.dll"); 

      bool isFree = FreeLibrary(p2); 
      isFree = FreeLibrary(p2); 
      p2 = LoadLibrary("TestLibrary.dll"); 
      val = GetValue(); 
     } 
    } 
} 

Das Seltsame ist, dass pinvoke noch funktioniert, wenn ich das Modul neu zu laden.
Soll das Modul nicht in einen anderen Teil des Speichers geladen werden?
Kann ich es so machen, wie ich es getan habe, oder werde ich Probleme damit haben?

Antwort

4

Wenn Sie ein Modul entladen und neu laden, wird es möglicherweise an einer anderen Adresse geladen. Oder es könnte an der gleichen Adresse geladen werden. Es hängt vom System ab, wo das Modul geladen werden soll. Wenn Sie neu laden, müssen Sie für jede importierte Funktion erneut GetProcAddress aufrufen, da sich die Adressen der Funktionen möglicherweise geändert haben, wenn das Modul an einer anderen Adresse geladen wurde.

Natürlich fehlt dieser Teil in Ihrem Code insgesamt. Der Teil, wo Sie GetProcAddress für jede Funktion aufrufen, die Sie importieren. Sie müssen es so machen, wenn Sie neu laden wollen. Andernfalls wird das Modul möglicherweise an einer anderen Adresse geladen und dann fällt alles um, wie in dem Thema erläutert, mit dem Sie verbunden sind.

Es scheint, als ob Sie Pech gehabt haben und das Modul an der gleichen Adresse neu geladen wird. Ich sage Pech, weil Sie nicht in der Lage waren, den Fehlermodus zu beobachten, und irrtümlich versucht zu glauben, dass Ihr Code korrekt ist.

Also müssen Sie p/aufrufen direkt auf das Modul und erhalten Sie alle Funktionszeiger durch den Aufruf GetProcAddress. Konvertieren Sie diese in Delegaten mit Marshal.GetDelegateForFunctionPointer.

+0

Meinten Sie "Marshal.GetDelegateForFunctionPointer"? :) – Idov

+0

Ja tat ich. Gehirn einfrieren. –