我需要在C项目中使用C库。我该怎么办?
更具体地说:为了提高效率,我需要使用strtod函数从字符串中提取两个值(比如“9.63074、9.63074-5.55708e-0060、0 1477.78”)。如果您有关于如何优化此操作的建议,请不要害羞,但主要问题仍然是按标题指定的问题。
最佳答案
我认为p/invoking tostrtod
不太可能比纯C解决方案更有效。在托管/非托管转换中有一个开销,我认为这对于像strtod
这样微不足道的事情来说是非常重要的。我自己会使用一个C#标记器,与double.Parse
结合使用。
最简单的C#标记器是String.Split()
,它产生这个例程:
static List<double> getValues(string str)
{
List<double> list = new List<double>();
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
不会因为伪逗号而标记它。