2010-05-12 2 views
6

Sto utilizzando una dll esterna non gestita utilizzando PInvoke e l'attributo DllImport. per esempio.Imposta dinamicamente l'attributo DllImport

[DllImport("mcs_apiD.dll", CharSet = CharSet.Auto)] 
private static extern byte start_api(byte pid, byte stat, byte dbg, byte ka); 

Mi chiedo se è possibile modificare i dettagli del file DLL (mcs_apiD.dll in questo esempio) dynmically in qualche modo, se per esempio ho voluto costruire contro un'altra versione dll

risposta

2

è possibile cambiare il nome della DLL ma puoi modificare il percorso della libreria che viene caricata (come leggendola dal registro o da un file di configurazione) e caricarla manualmente con la funzione del kernel32 LoadLibrary: see my answer there.

+0

Ok. Ma nel mio esempio ho specificato un prototipo di funzione specifica in modo da poter eseguire correttamente il marshalling dei parametri, alcune delle funzioni api hanno strutture complesse come parametri. Come dovrei farlo quando lavoro in questo modo? – user226356

+0

se i parametri cambiano da una versione della DLL a un'altra, sei sfortunato con il metodo che ho citato –

5

Sì, questo è possibile, devi fare parte del lavoro che fa il marshaller P/Invoke. Caricamento della DLL e ricerca del punto di ingresso della funzione esportata. Inizia dichiarando un delegato la cui firma corrisponde la funzione esportata:

private delegate byte start_api(byte pid, byte stat, byte dbg, byte ka); 

Quindi utilizzare il codice come questo:

using System.ComponentModel; 
using System.Runtime.InteropServices; 
    ... 

    static IntPtr dllHandle; 
    ... 
     if (dllHandle == IntPtr.Zero) { 
      dllHandle = LoadLibrary("mcs_apiD.dll"); 
      if (dllHandle == IntPtr.Zero) throw new Win32Exception(); 
     } 
     IntPtr addr = GetProcAddress(dllHandle, "[email protected]"); 
     if (addr == IntPtr.Zero) throw new Win32Exception(); 
     var func = (start_api)Marshal.GetDelegateForFunctionPointer(addr, typeof(start_api)); 
     var retval = func(1, 2, 3, 4); 
    ... 
    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    private static extern IntPtr LoadLibrary(string name); 
    [DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)] 
    private static extern IntPtr GetProcAddress(IntPtr hModule, string name); 

Un sacco di modi per ottenere questo torto, naturalmente. Si noti che è necessario utilizzare il nome esportato effettivo dalla DLL, non si ottiene più l'aiuto dal marshaller P/Invoke per aiutare con la decorazione del nome. Utilizzare dumpbin.exe/exports nella DLL se non si è certi del nome dell'esportazione.

+0

, in effetti, con un tipo di delegato per versione dell'API DLL combinato con GetProcAddress, uscirai da it –

+0

C'è un articolo del blog di Microsoft su questo all'indirizzo: http://blogs.msdn.com/b/jonathanswift/archive/2006/10/03/dynamically-calling-an-unmanaged-dll-from-.net-_2800_c_23002900_ aspx – Deanna