问题描述
我需要在C#项目中使用C库。我该怎么办?
I need to use the C library in a C# project. How can I do?
更具体地说:出于效率考虑,我需要使用函数从字符串中提取双精度值(例如 9.63074,9.63074 -5.55708e-006 0,0 1477.78)。如果您对如何优化此操作有任何建议,请不要害羞,但主要问题仍然是标题指定的问题。
To be more specific: for reasons of efficiency I need to use the strtod function to extract double values from a string (like this "9.63074,9.63074 -5.55708e-006 0 ,0 1477.78"). If you have suggestions about how to optimize this operation do not be shy, but the main question remains that specified by title.
推荐答案
我认为p /调用 strtod
不可能比纯C#解决方案更有效。在托管/非托管转换中会产生开销,我认为这对于 strtod
这样琐碎的事情来说意义重大。我自己会使用C#令牌生成器,并结合 double.Parse
。
I think it very unlikely that p/invoking to strtod
would be more efficient than a pure C# solution. There is an overhead in managed/unmanaged transitions and I would think that would be significant for something as trivial as strtod
. Myself I would use a C# tokenizer, combined with double.Parse
.
最简单的C#令牌生成器是 String.Split()
产生以下例程:
The simplest C# tokenizer is String.Split()
which yields this routine:
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
的方式,请记住,我建议您不要在实际代码中使用此方法。
However, since I enjoy p/invoke, here's how you would call strtod
from C#, bearing in mind that I recommend you don't use this approach in real code.
[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
的话,就需要按照我的说明进行操作。
I'm passing the string as an IntPtr
because you would be calling strtod
repeatedly to walk across the entire buffer. I didn't show that here, but if you are going to make any use of endptr
then you need to do it as I illustrate.
当然,要有效地远程使用 strtod
,您需要访问全局 errno
变量。您需要处理全局变量的事实应该足以警告您这是龙。而且,通过 errno
提供的错误报告非常有限。但是,如果需要,它在这里:
Of course, to use strtod
remotely effectively you need to gain access to the errno
global variable. The very fact that you need to deal with a global variable should be warning enough that here be dragons. What's more, the error reporting offered through errno
is exceedingly limited. However, if you want it, here it is:
[DllImport(@"msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
static extern int _get_errno();
最后一点。您建议的输入字符串为
One final point. Your suggested input string is
"9.63074,9.63074 -5.55708e-006 0 ,0 1477.78"
,但由于虚假逗号, strtod
不会对此进行标记。
but strtod
won't tokenize that because of the spurious commas.
这篇关于在.NET中使用C库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!