9
votes

Réglage de Dllimport Programmatiquement en C #

J'utilise dllimport dans ma solution.
Mon problème est que j'ai deux versions de la même dll, construites pour 32 bits et une autre pour 64 bits.

Ils exposent les mêmes fonctions avec des noms identiques et des signatures identiques. Mon problème est que je dois utiliser deux méthodes statiques qui exposent ces expositions, puis à la taille de l'heure d'exécution, utilisez intPTR pour déterminer le bon à invoquer. xxx p> Je dois le faire parce que mydllname32 et mydllName64 doit être constant et je n'ai pas trouvé de moyen de la définir au moment de l'exécution.

fait Quelqu'un a une solution élégante pour cela afin que je puisse vous débarrasser de la duplication de code et de la vérification de la taille intPTR

si je pouvais définir le nom du fichier, je ne devrais que Vérifiez une fois et je pourrais vous débarrasser d'une tonne de code répété.


1 commentaires

Aucun sens de la sélectionner au moment de l'exécution si la différence est la compilation entière.


9 Réponses :


13
votes

Vous pouvez probablement y parvenir avec le mot clé #if code>. Si vous définissez un symbole de compilateur conditionnel appelé win32 code>, le code suivant utilisera le bloc Win32, si vous le supprimez, il utilisera l'autre bloc:

    private static class ccf
    {
#if win32
        [DllImport(myDllName32)]
        public static extern int func1();
#else    
        [DllImport(myDllName64)]
        public static extern int func1();
#endif
    }


2 commentaires

Ouais, mais j'aimerais garder l'option "Toute CPU" par opposition à avoir des versions 32 et 64 bits.


Bien que cela fonctionne, cette approche entraîne toujours la duplication de code L'affiche d'origine souhaite éviter, plus vous limite à compiler des versions séparées pour 32 et 64 bits. Vous pouvez supprimer la duplication de code et continuer à cibler les versions 32 et 64 bits avec une DLL / EXE compilée en prenant une approche de DIANIS pour utiliser SETDLLDIRECTORY, ou la mine à utiliser LoadLibrary.



2
votes

Pourquoi ne pas les envelopper dans une méthode? XXX


2 commentaires

C'est essentiellement ce que j'ai maintenant :-)


Eh bien, une fois que vous l'enveloppez, vous n'avez pas à vous en soucier.



1
votes

Une option alternative consiste à avoir à la fois les versions 32 et 64 bits de la DLL non gétionnée ont le même nom, mais les avoir à vivre dans des dossiers séparés dans votre sortie de construction (disons, x86 \ et x64 \).

Ensuite, votre installation d'installation ou autre que vous distribuez ceci est mise à jour, il est donc disponible pour installer la DLL appropriée pour la plate-forme qu'il installe sur.


0 commentaires

0
votes

Vous ne pouvez pas faire cela comme vous voulez. Vous devez penser à l'attribut dllimport en tant que métadonnées utilisées lors de la compilation. En conséquence, vous ne pouvez pas changer la DLL, il importe de manière dynamique.

Si vous souhaitez conserver votre code géré ciblé sur "Toute CPU", vous devez également importer les bibliothèques 32 bits et 64 bits enveloppées comme deux fonctions différentes que vous pouvez appeler en fonction de l'environnement d'exécution ou d'utiliser certains Des appels d'API Win32 supplémentaires pour charger tardivement la version correcte de l'assemblage non géré à l'exécution et des appels Win32 supplémentaires pour exécuter les méthodes requises. L'inconvénient est que vous n'aurez pas de support de temps de compilation pour aucun de ce type de code pour la sécurité de type, etc.


0 commentaires

0
votes

hmm, je me demande si vous pouviez créer une interface, puis une classe avec les méthodes basées sur les DLL 32 bits et 64 bits.

Je ne suis pas sûr que s'il existe une méthode explicite pour déterminer si vous exécutez 64 bits, mais ce qui suit pourrait fonctionner: Autoriser le code dangereux et avoir une fonction dangereuse qui obtient un pointeur à une adresse, puis déterminez si le pointeur est de 4 ou 8 octets de taille. Sur la base du résultat, déterminez la mise en œuvre de l'interface à créer.


0 commentaires

0
votes

Vous pouvez déterminer si vous exécutez 64bits ou non en cochant la taille du type INTPTR (appelé Native Int de toute façon). Ensuite, vous pouvez charger la DLL d'approporation à l'aide d'un appel de LoadLibraryw importé, obtenez le pointeur de fonction à l'aide de getProcAddress, puis découvrez Marshal.getDelegatefunctionPoinger

Ce n'est pas aussi compliqué que cela puisse ressembler. Vous devez dllimport à la fois LoadLibraryw et GetProcAddress.


0 commentaires


10
votes

1 commentaires

C'est une excellente approche, surtout si vous avez plusieurs dlls dont vous avez besoin de versions 32 et 64 bits de. Je pense que j'aime bien l'approche SetdllDirectory encore mieux que d'utiliser la méthode Loaddll que j'ai expliquée dans ma réponse. C'est aussi beaucoup moins de code que les approches de l'emballage, et vous compilons une CPU.



1
votes

Vous pouvez créer deux méthodes et choisir une dans une heure d'exécution, vous pouvez donc conserver n'importe quel CPU xxx

}


0 commentaires