2013-05-13 1 views
1

J'ai un fichier .DLL externe avec un code assembleur rapide à l'intérieur. Quelle est la meilleure façon d'appeler des fonctions dans ce fichier .DLL pour obtenir les meilleures performances?DllImport ou LoadLibrary pour de meilleures performances

+1

sont ces * grandes méthodes * qui sont appelées seulement quelques fois ou sont ces méthodes * slim * qui s'appellent très souvent du code managé? – Oliver

+0

Je me souviens que les gars de [SharpDX] (http://sharpdx.org/) ont analysé le code produit par 'DLLImport' et que le plus gros problème de performance était une sorte de vérification des paramètres (inutiles). Pour cette raison, ils ont utilisé 'Reflection.Emit()' pour générer le même code comme 'DLLImport' mais sans les vérifications, ce qui conduit à une amélioration des performances. Je pense que c'était un billet de blog de l'un de ses créateurs, mais je ne peux pas le trouver pour le moment. – Oliver

+0

@Olivier, ces méthodes remplissent par exemple des buffers de 1024 octets. – zgnilec

Répondre

0

Je pense que DLLImport et LoadLibrary ont des objectifs différents. Si vous utilisez .dll natif, vous devez utiliser DllImport. Si vous utilisez l'assembly .NET, vous devez utiliser LoadAssembly.

En fait, vous pouvez charger dynamiquement l'ensemble natif aussi, voir cet exemple: dynamically-calling-an-unmanaged-dll-from-.net

+0

"En fait, vous pouvez aussi charger dynamiquement l'assemblage natif". Clairement, @zgnilec le sait déjà. –

0

La seule façon de répondre à cette question est à temps les deux options, une tâche qui est trivialement facile. Faire des prédictions de performance sans timing est inutile.

Puisque nous n'avons pas votre code, vous seul pouvez répondre à votre question.

+0

Je vais vérifier cela, peut-être que je n'ai pas fait questuon trop clairement, je demandais différentes méthodes d'utilisation des DDL externes. Je ne "connais" que ces deux-là. Quelque part je lis DllImport fait des choses à l'intérieur, comme épingler l'objet géré pour le garbage colector etc. Je pense qu'il y a une manière spéciale d'appeler les méthodes d'assembleur natives. Si je vais faire dll thats fournir la fonction y = x^2 (juste un exemple) et puis l'appeler en utilisant DllImport qui fera 99% cpu sur le mécanisme DllImport, puis 1% pour ma fonction assembleur, alors n'est pas utile d'utiliser des DLL externes: / – zgnilec

1

En supposant que votre plate-forme cible est la même que cette DLL native. Vous pouvez utiliser DLLImport pour épingler LoadLibrary et utiliser LoadLibrary pour charger la DLL native dans votre processus. Ensuite, utilisez DllImport pour épingler GetProcAddress.

Ensuite, vous pouvez définir des délégués pour toutes les méthodes exportées dans cette DLL que vous souhaitez appeler.

Ensuite, vous utilisez Marshal.GetDelegateForFunctionPointer pour définir votre délégué à partir de GetProcAddress.

Vous créez une classe statique qui effectue cette opération une fois dans le constructeur. Ensuite, vous pouvez appeler vos délégués pour appeler les fonctions exportées natives dans la DLL, sans avoir DllImport sur tout. Beaucoup plus propre, et je suis à peu près sûr que c'est beaucoup plus rapide et va probablement complètement contourner avant les contrôles de paramètres mentionnés. Donc, vous auriez une initialisation lente, mais une fois chargé, s'exécuterait rapidement imo. Je n'ai pas testé cela.

Voici un blog de ma source.

http://blogs.msdn.com/b/jonathanswift/archive/2006/10/03/dynamically-calling-an-unmanaged-dll-from-.net-_2800_c_23002900_.aspx

5

Votre DLL est peut-être en python ou C++, quelle que soit, faire la même chose comme suit.

Ceci est votre fichier DLL en C++.

tête:

extern "C" __declspec(dllexport) int MultiplyByTen(int numberToMultiply); 

fichier code source

#include "DynamicDLLToCall.h" 

int MultiplyByTen(int numberToMultiply) 
{ 
    int returnValue = numberToMultiply * 10; 
    return returnValue; 
} 

Jetez un oeil au code C#:

static class NativeMethods 
{ 
    [DllImport("kernel32.dll")] 
    public static extern IntPtr LoadLibrary(string dllToLoad); 

    [DllImport("kernel32.dll")] 
    public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName); 

    [DllImport("kernel32.dll")] 
    public static extern bool FreeLibrary(IntPtr hModule); 
} 

class Program 
{ 
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 
    private delegate int MultiplyByTen(int numberToMultiply); 

    static void Main(string[] args) 
    { 
      IntPtr pDll = NativeMethods.LoadLibrary(@"PathToYourDll.DLL"); 
      //oh dear, error handling here 
      //if (pDll == IntPtr.Zero) 

      IntPtr pAddressOfFunctionToCall = NativeMethods.GetProcAddress(pDll, "MultiplyByTen"); 
      //oh dear, error handling here 
      //if(pAddressOfFunctionToCall == IntPtr.Zero) 

      MultiplyByTen multiplyByTen = (MultiplyByTen)Marshal.GetDelegateForFunctionPointer(
                        pAddressOfFunctionToCall, 
                        typeof(MultiplyByTen)); 

      int theResult = multiplyByTen(10); 

      bool result = NativeMethods.FreeLibrary(pDll); 
      //remaining code here 

      Console.WriteLine(theResult); 
    } 
} 
Questions connexes