2010-05-12 22 views
6

PInvoke ve DllImport özniteliğini kullanarak harici bir yönetilmeyen dll kullanıyorum. Örneğin. bazı tarzda dynmically (bu örnekte mcs_apiD.dll) dll dosyası ayrıntıları değiştirmek mümkün olup olmadığını, örneğin başka bir dll sürümü karşı inşa etmek istiyorsaDinamik olarak DllImport özniteliğini ayarlayın

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

Ben merak ediyorum

cevap

2

yapabilirsiniz dll'nin adını değiştirmeyin, ancak yüklenen kitaplık yolunu (kayıt defterinden veya yapılandırma dosyasından okuyarak) değiştirebilir ve el ile LoadLibrary kernel32 işlevini kullanarak yükleyebilirsiniz: see my answer there.

+0

Tamam. Ama benim örneğimde, parametreleri doğru şekilde seçebilmem için belirli bir işlev prototipini belirledim, bazı api işlevlerinin parametre olarak karmaşık yapıları var. Bu şekilde çalışırken bunu nasıl yapardım? – user226356

+0

Parametreler DLL'nin bir sürümünden diğerine değişirse, GetProcAddress ile birlikte DLL API'sinin sürümü başına 1 delege türüyle, gerçekten –

5

Evet, bu mümkündür, P/Invoke marshaller'ın yaptığı işin bir kısmını yapmak zorundasınız. DLL yükleniyor ve verilen işlevin giriş noktasını bulmak. İmzasını ihraç işlevi eşleşen bir temsilci bildirirken başlayın:

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

Sonra böyle kodu kullanın: Elbette bu yanlış elde etmenin yollarını

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

sürü. Dışa aktarılan adı DLL'den kullanmanız gerektiğine dikkat edin, artık P/Invoke marshaller'in ad dekorasyonuna yardımcı olması için yardım almazsınız. Dışa aktarma adının neye benzediğinden emin değilseniz, dumpbin.exe/Export'u DLL'de kullanın.

+0

numaralı yöntemden bahsettiğim yöntemle şansınız yok demektir. –

+0

Bu konuda bir Microsoft blog makalesi var: http://blogs.msdn.com/b/jonathanswift/archive/2006/10/03/dynamically-calling-an-unmanaged-dll-from-.net-_2800_c_23002900_ .aspx – Deanna

İlgili konular