在.NET中使用C库

gli*_*ite 0 c c# pinvoke dllimport

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

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

Dav*_*nan 6

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

最简单的C#tokenizer是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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

你可以这样称呼它:

IntPtr str = Marshal.StringToHGlobalAnsi(inputStr);
IntPtr endptr = IntPtr.Zero;
double val = strtod(str, ref endptr);
Marshal.FreeHGlobal(str);
Run Code Online (Sandbox Code Playgroud)

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

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

[DllImport(@"msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
static extern int _get_errno();
Run Code Online (Sandbox Code Playgroud)

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

"9.63074,9.63074 -5.55708e-006 0 ,0 1477.78"
Run Code Online (Sandbox Code Playgroud)

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