在ImplicitOperator中使用David Brown的可下载示例我将一个经常工作的DOT文件的GraphViz渲染器组合到一个内存中的图像中.
不幸的是,我的版本因为我已经使用IIS 7 ASP.NET Web应用程序的8次执行中的1次失败率而失败.我知道DOT文件数据是一致的,因为我将失败的实例与工作实例,它们是相同的.
由于大卫的网站似乎暗示博客的未来不确定,我将在这里重新打印互联网文章.希望他不介意.失败是在示例的末尾,在第三个语句集的RenderImage中.我已经注意到// TODO的失败行:......失败总是发生在那里(如果它发生的话).通过这一行,g和gvc指针不为零,并且正确填充了布局字符串.
我真的不希望任何人在运行时调试它.相反,我希望对互操作代码的一些静态分析可能会揭示问题.我想不出任何先进的编组技术 - 两个IntPtrs和一个字符串不需要很多帮助,对吧?
谢谢!
旁注:我看了一下MSAGL的试用版,我没有留下深刻的印象 - 微软99美元,我希望节点布局和/或文档的更多功能可以解释我所缺少的内容.也许我从QuickGraph到AGL的快速端口不公平地偏向于我的经验,因为这些方法存在一些根本的差异(例如,以边缘为中心与以节点为中心).
public static class Graphviz
{
public const string LIB_GVC = "gvc.dll";
public const string LIB_GRAPH = "graph.dll";
public const int SUCCESS = 0;
/// <summary>
/// Creates a new Graphviz context.
/// </summary>
[DllImport(LIB_GVC)]
public static extern IntPtr gvContext();
/// <summary>
/// Releases a context's resources.
/// </summary>
[DllImport(LIB_GVC)]
public static extern int gvFreeContext(IntPtr gvc);
/// <summary>
/// Reads a …Run Code Online (Sandbox Code Playgroud) 在VS2010中,如果使用错误的调用约定调用函数,则托管调试助手将为您提供pInvokeStackImbalance异常(pInvokeStackImbalance MDA),这通常是因为在调用C库时未指定CallingConvention = Cdecl.比如你写的
[DllImport("some_c_lib.dll")]
static extern void my_c_function(int arg1, int arg2);
Run Code Online (Sandbox Code Playgroud)
代替
[DllImport("some_c_lib.dll", CallingConvention=CallingConvention.Cdecl)]
static extern void my_c_function(int arg1, int arg2);
Run Code Online (Sandbox Code Playgroud)
因此获得了StdCall调用约定而不是Cdelc.
如果你回答这个问题,你已经知道了这个差异,但是对于这个线程的其他访问者:StdCall意味着被调用者清除堆栈中的参数,而Cdecl意味着调用者清理堆栈.
因此,如果您的C代码中的调用约定错误,则您的堆栈不会被清理并且程序崩溃.
但是,即使.NET程序使用StdCall进行Cdecl功能,.NET程序似乎也不会崩溃.默认情况下,VS2008上没有启用堆栈不平衡检查,因此一些VS2008项目使用了他们的作者不知道的错误调用约定.我刚尝试过GnuMpDotNet,即使缺少Cdelc声明,样本运行也很好.X-MPIR也是如此.
它们都在调试模式下抛出pInvokeStackImbalance MDA异常,但在发布模式下不会崩溃.为什么是这样?.NET VM是否将所有对本机代码的调用包装起来并在之后恢复堆栈本身?如果是这样,为什么还要使用CallingConvention属性呢?