我需要在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不会因为伪逗号而标记它。

10-06 04:08