在.NET中使用C库

我需要在C#项目中使用C库。 我能怎么做?

更具体一点:出于效率原因,我需要使用strtod函数从字符串中提取双值(如“9.63074,9.63074 -5.55708e-006 0,01477.78”)。 如果您有关于如何优化此操作的建议,请不要害羞,但主要问题仍然是标题指定。

我认为p /调用strtod不太可能比纯C#解决方案更有效。 托管/非托管转换中存在开销,我认为这对于像strtod一样微不足道的事情会很重要。 我自己会使用C#tokenizer,结合double.Parse

最简单的C#tokenizer是String.Split() ,它产生这个例程:

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

但是,因为我喜欢p / invoke,所以这里是你如何从C#调用strtod ,记住我建议你不要在实际代码中使用这种方法。

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

你可以这样称呼它:

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

我将字符串作为IntPtr传递,因为您将反复调用strtod来遍历整个缓冲区。 我没有在这里展示,但如果你打算使用endptr那么你需要按照我的说明去做。

当然,要有效地远程使用strtod您需要获得对errno全局变量的访问权限。 你需要处理一个全局变量的事实应该足够警告这里是龙。 更重要的是,通过errno提供的错误报告非常有限。 但是,如果你想要它,这里是:

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

最后一点。 您建议的输入字符串是

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

但是strtod不会因为虚假的逗号而将其标记出来。

首先,您并不理解托管代码和非托管代码之间的调用相对昂贵,而且不是免费的。 所以,从你告诉我们的内容来看,听起来你会多次从托管代码中调用strtod 。 你必须测试它,但是pinvoke惩罚可能会抵消任何性能提升。

另外,您是否实际测试过以确保strtod在您的用例中比托管版本更快? 我的测试表明, double.Parse实际上超过100,000次迭代。 ( strtod需要大约54ms, double.Parse在三次运行中花了大约15次。如果你愿意,我可以给你代码。)

这听起来像是一种误导性的尝试,即优化一段甚至尚未经过测试的代码。 你确定你正在解决正确的问题吗?

为什么不使用double.Parse()

 double asDouble = double.Parse(myInput); 

要回答如何在.NET中使用C库的问题:您可以做的一件事是创建一个您想要的C调用函数。 从那里,你需要将它构建为DLL。 完成后,您将能够从C#进行P / Invoke。

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 /库/ ms235282(v = VS.80)的.aspx

另一种可能性是将其构建为混合组件。

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

也就是说,在你的具体情况下,我强烈建议看看double.Parse()除非有充分的理由否则。

大卫告诉你如何通过p / invoke来做到这一点。 但是,.NET的方法是使用Regex 。 以下内容可能对您有用:

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

此代码将字符串中的所有双精度数添加到通用List集合中。 注意我没有针对你的字符串测试正则表达式代码,但这给你一个想法。