Utiliser la bibliothèque C dans .NET

J’ai besoin d’utiliser la bibliothèque C dans un projet C #. Comment puis-je faire?

Pour être plus précis: pour des raisons d’efficacité, je dois utiliser la fonction strtod pour extraire les valeurs doubles d’une chaîne (comme ceci “9.63074,9.63074 -5.55708e-006 0, 0 1477.78”). Si vous avez des suggestions pour optimiser cette opération, ne vous gênez pas, mais la question principale rest celle spécifiée par le titre.

Je pense qu’il est très peu probable que l’invocation de p / à strtod soit plus efficace qu’une solution C # pure. Il y a des frais généraux dans les transitions gérées / non gérées et je pense que cela serait significatif pour quelque chose d’aussi sortingvial que strtod . J’utiliserais moi-même un tokenizer C #, combiné à double.Parse .

Le tokenizer C # le plus simple est Ssortingng.Split() qui donne cette routine:

 static List getValues(ssortingng str) { List list = new List(); foreach (ssortingng item in str.Split(default(Char[]), SsortingngSplitOptions.RemoveEmptyEnsortinges)) list.Add(double.Parse(item)); return list; } 

Cependant, comme j’apprécie p / invoke, voici comment appeler strtod de C #, tout en gardant à l’esprit que je vous recommande de ne pas utiliser cette approche dans du code réel.

 [DllImport(@"msvcrt.dll", CallingConvention=CallingConvention.Cdecl)] static extern double strtod(IntPtr str, ref IntPtr endptr); 

Vous pouvez l’appeler comme ça:

 IntPtr str = Marshal.SsortingngToHGlobalAnsi(inputStr); IntPtr endptr = IntPtr.Zero; double val = strtod(str, ref endptr); Marshal.FreeHGlobal(str); 

Je passe la chaîne en tant que IntPtr parce que vous appelez strtod plusieurs resockets pour parcourir la totalité du tampon. Je n’ai pas montré cela ici, mais si vous comptez utiliser endptr vous devez le faire de la manière illustrée.

Bien sûr, pour utiliser efficacement strtod distance, vous devez avoir access à la variable globale errno . Le fait même que vous ayez besoin de traiter une variable globale devrait être suffisamment prévenant qu’il s’agisse de dragons. De plus, le rapport d’erreur proposé par errno est extrêmement limité. Cependant, si vous le voulez, le voici:

 [DllImport(@"msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] static extern int _get_errno(); 

Un dernier point. Votre chaîne de saisie suggérée est

 "9.63074,9.63074 -5.55708e-006 0 ,0 1477.78" 

mais strtod ne le fera pas à cause des fausses virgules.

Tout d’abord, vous ne réalisez pas que les appels entre le code géré et le code non géré sont relativement coûteux, ce n’est pas gratuit. Donc, d’après ce que vous nous avez dit, il semble que vous appelez strtod plusieurs fois à partir de code géré. Vous devrez le tester, mais la pénalité «pinvoke» risque d’annuler les gains de performances.

En outre, avez-vous réellement testé pour vous assurer que strtod est plus rapide dans votre cas d’utilisation que ne le serait la version gérée? Mes tests ont montré que double.Parse est en fait plus rapide sur 100 000 itérations. ( strtod pris environ double.Parse , double.Parse pris environ 15 points sur trois. Je peux vous donner le code si vous le souhaitez.)

Cela ressemble à une tentative peu judicieuse d’optimiser un morceau de code qui n’a même pas été testé. Êtes-vous sûr de résoudre le bon problème?

Pourquoi ne pas utiliser double.Parse() ?

 double asDouble = double.Parse(myInput); 

Pour répondre à la question de savoir comment utiliser une bibliothèque C dans .NET: Vous pouvez notamment créer une fonction que le C appelle comme vous le souhaitez. À partir de là, vous devrez le construire en tant que DLL. Une fois que cela est fait, vous pourrez P / Invoke à partir de C #.

http://www.codeproject.com/Articles/9826/How-to-create-a-DLL-library-in-C-and-then-use-it-w http://msdn.microsoft.com/en -us / bibliothèque / ms235282 (v = vs.80) .aspx

Une autre possibilité est de construire cela comme un assemblage mixte.

http://msdn.microsoft.com/en-us/library/x0w2664k.aspx

Cela dit, dans votre cas particulier, je suggérerais fortement de regarder double.Parse () sauf s’il existe une bonne raison.

David vous a montré comment faire via p / invoke. Cependant, la méthode .NET consiste à utiliser Regex . Quelque chose comme ce qui suit pourrait fonctionner pour vous:

  MatchCollection matches = Regex.Matches(inputSsortingng, @".*?([-]{0,1} *\d+.\d+)"); List doubles = new List(); foreach (Match match in matches) { ssortingng value = match.Groups[1].Value; value = value.Replace(" ", ""); doubles.Add(double.Parse(value)); } 

Ce code appenda tous les doublons d’une chaîne dans une collection générique List . Notez que je n’ai pas testé le code Regex avec votre chaîne, mais cela vous donne une idée.