无法使用点布局(graphviz作为库)

Unable to use dot layout (graphviz as a library)

本文关键字:graphviz 布局      更新时间:2023-10-16

我在C++应用程序中使用graphviz(v2.28.0)作为库,并且我希望使用点布局来渲染图形。一切都很好,直到我调用gvLayout(_context,_graph,"dot")函数,输出以下错误:

 Error: Layout type: "dot" not recognized. Use one of:

链接时我使用以下库标志:

-lgvc -lgraph -lpathplan -lcdt -lgvplugin_dot_layout

从Unix命令行调用dot可以正常工作。我做错了什么?

你可能已经解决了这个问题,或者放弃了,但我最终来到了这里,所以我相信其他人会。。。

插件需要显式加载。我不确定这是否与静态链接有关,或者在将graphviz用作库时是否需要这样做。

这个固定点对我来说:

extern gvplugin_library_t gvplugin_dot_layout_LTX_library;
gvAddLibrary(gvc, &gvplugin_dot_layout_LTX_library);

当我在macosx上编译graphviz时,将"-O2"优化标志添加到gcc时,我遇到了这个错误。当我删除该标志时,错误就消失了。

您在动态库加载中使用graphviz吗?在静态环境中,以下几行可能会有所帮助:

#include "gvplugin.h"
extern gvplugin_library_t gvplugin_dot_layout_LTX_library;
extern gvplugin_library_t gvplugin_neato_layout_LTX_library;
extern gvplugin_library_t gvplugin_core_LTX_library;
extern gvplugin_library_t gvplugin_quartz_LTX_library;
extern gvplugin_library_t gvplugin_visio_LTX_library;
lt_symlist_t lt_preloaded_symbols[] =
{
    { "gvplugin_dot_layout_LTX_library", &gvplugin_dot_layout_LTX_library},
    { "gvplugin_neato_layout_LTX_library", &gvplugin_neato_layout_LTX_library},
    { "gvplugin_core_LTX_library", &gvplugin_core_LTX_library},
    { "gvplugin_quartz_LTX_library", &gvplugin_quartz_LTX_library},
    { "gvplugin_visio_LTX_library", &gvplugin_visio_LTX_library},
    { 0, 0}
};

根据Emden R.Gansner在"graphviz兴趣"邮件列表上的回复,此错误消息表明软件无法找到graphviz配置文件。

graphviz配置文件(config6)由gvc库用于根据需要加载各种libgvplugin_...库。

Gansner还提到,graphviz支持GVBINDIR环境变量,如果定义了该变量,则该变量用于指定包含graphviz配置文件的目录。这也在How to configure&适用于Mac应用商店的Graphviz软件包?。

在我的情况下(我试图将graphviz库包含在macOS/Objective-C框架中),框架子目录(称为"库")包含config6文件和这些libgvplugin_...库(位于常规graphviz库旁):

Libraries:
    config6
    libgvplugin_core.6.dylib
    libgvplugin_dot_layout.6.dylib
    libgvplugin_gd.6.dylib
    libgvplugin_neato_layout.6.dylib
    libgvplugin_quartz.6.dylib

从框架的一个类中,可以设置GVBINDIR环境变量,如下所示:

NSBundle *containingBundle = [NSBundle bundleForClass:[self class]];
NSURL *librariesDirURL = [[containingBundle bundleURL] URLByAppendingPathComponent:@"Versions/A/Libraries" isDirectory:YES];
if (librariesDirURL) {
    setenv("GVBINDIR", (char*)[[librariesDirURL path] UTF8String], 1);
}

设置GVBINDIR环境变量是唯一对我有效的解决方案

我还尝试了上面其他人提到的解决方案,包括显式加载默认的graphviz插件。例如,_graphContext被定义为static GVC_t *_graphContext,此代码:

extern gvplugin_library_t gvplugin_dot_layout_LTX_library;
extern gvplugin_library_t gvplugin_neato_layout_LTX_library;
extern gvplugin_library_t gvplugin_core_LTX_library;
extern gvplugin_library_t gvplugin_quartz_LTX_library;
lt_symlist_t lt_preloaded_symbols[] =
{
    { "gvplugin_dot_layout_LTX_library", &gvplugin_dot_layout_LTX_library},
    { "gvplugin_neato_layout_LTX_library", &gvplugin_neato_layout_LTX_library},
    { "gvplugin_core_LTX_library", &gvplugin_core_LTX_library},
    { "gvplugin_quartz_LTX_library", &gvplugin_quartz_LTX_library},
    { 0, 0}
};
_graphContext = gvContextPlugins(lt_preloaded_symbols, 1);

实际上对我有效。也就是说,这导致graphviz插件加载,上面提到的错误消息("错误:布局类型:"点"无法识别。使用其中一个:")消失了。然而,随后对gvLayout()的任何调用都会导致我的graphviz崩溃(EXC_BAD_ACCESS

所以现在我采用的是环境变量法。