C++ 使用带有在头文件中定义的全局变量的 C 库

Posted

技术标签:

【中文标题】C++ 使用带有在头文件中定义的全局变量的 C 库【英文标题】:C++ using C library with global variables defined in the header file 【发布时间】:2015-05-14 16:43:55 【问题描述】:

我的意图是将用 C 编写的 LKH TSP 算法包含到我的 C++ 项目中。

LKH:http://www.akira.ruc.dk/~keld/research/LKH/

来源:http://www.akira.ruc.dk/~keld/research/LKH/LKH-2.0.7.tgz

首先我开始编写一个 CMakeLists.txt 来创建一个不包含 LKHmain.c 的库。

file(GLOB_RECURSE SOURCES SRC/*.c)
file(GLOB_RECURSE HEADERS SRC/INCLUDE/*.h)

include_directories($CMAKE_CURRENT_SOURCE_DIR/SRC/INCLUDE)

set(LIB_SOURCES $SOURCES)
list(REMOVE_ITEM LIB_SOURCES $CMAKE_CURRENT_SOURCE_DIR/SRC/LKHmain.c)

add_library(lkh
    $LIB_SOURCES
)
target_link_libraries(lkh m)

之后我想实现两个使用该库的函数。 第一个只是读取 TSPLib 的文件并将值复制到我自己的 Map 结构中。 第二个应该通过使用我的地图结构而不读取任何文件来解决 TSP 问题。 (程序通常只能通过读取文件来使用,所以这是一个包装部分)

现在我的问题: 所有变量都在 LKH.h 中定义并由所有实现使用。所以例如

LKH.h

int TraceLevel; /* Specifies the level of detail of the output
               given during the solution process.
               The value 0 signifies a minimum amount of
               output. The higher the value is the more
               information is given */
Node *FirstNode;        /* First node in the list of nodes */
int InitialTourAlgorithm;

现在它们在 *.c 类中使用。

GreedyTour.c

#include "LKH.h"


GainType GreedyTour()

    Node *From, *To, *First, *Last = 0, **Perm;
    int Count, i;
    double EntryTime = GetTime();

    if (TraceLevel >= 1) 
        if (InitialTourAlgorithm == BORUVKA)
            printff("Boruvka = ");
        else if (InitialTourAlgorithm == GREEDY)
            printff("Greedy = ");
        else if (InitialTourAlgorithm == NEAREST_NEIGHBOR)
            printff("Nearest-Neighbor = ");
        else if (InitialTourAlgorithm == QUICK_BORUVKA)
            printff("Quick-Boruvka = ");
    
    Cost = 0;
    EdgesInFragments = 0;
    From = FirstNode;
    do 
        From->Degree = 0;
        From->Tail = From;
        From->Mark = 0;
        From->Next = From->Suc;
        From->Pred = From->Suc = 0;
    
    while ((From = From->Next) != FirstNode);

..........
..........

在本例中,变量 TraceLevel、InitialTourAlgorithm 和 FirstNode 用作全局变量。

我的问题:当我在课堂上加入 LKH.h 时,会产生很多副作用。执行一个方法后,全局变量发生了变化。 我想重置所有这些以执行下一个方法,而无需任何先前设置的值。 我写了几个测试用例,gtest 方法有奇怪的效果,我认为这是由全局变量行为引起的。

这里是我的包装文件:

lkh.h

#include "model/map.h"

namespace ttp 

    class LKHWrapper 

    public:

        MapPtr createMap(std::string);

        int *calc(MapPtr map);

    ;


lkh.cpp

#include <fstream>
#include <limits>
#include "lkh.h"

extern "C"

#include "LKH.h"
#include "Genetic.h"
#include "Heap.h"


namespace ttp 

    MapPtr LKHWrapper::createMap(std::string pathToFile) 
        ...
        [change global variables]
        ...
        return map;

    

    int* LKHWrapper::calc(MapPtr map) 
        ...
        [change global variables]
        ...
        return BestTour
    

解决该问题并获得这两种方法的无副作用实施的最简单方法是什么?

@Mason Watmough:

是的,但问题是我没有自己定义它们。我必须使用

 extern "C"
    
    #include "LKH.h"
    #include "Genetic.h"
    #include "Heap.h"
    

定义和声明变量(参见 C 程序中的 LKH.h)

并且没有冲突或链接错误! 通过包含 LKH.h,变量仅在 lkh.cpp 中存在一次。 库 liblkh.a 也没有此变量,因为它们仅在 LKH.h 中定义。

【问题讨论】:

全局变量每个进程只存在一次。如果您的库使用全局变量,您就没有机会根据您的需要将它们设置为本地变量。这样做的唯一方法是创建单独的进程。提示:请编写更小的示例和代码 sn-ps,如果可能的话,可以编译和测试。 LKH 出现同样的问题 - 您找到解决方案了吗? 【参考方案1】:

如果您的全局变量在您的头文件以及您的 c 程序中定义,您将需要选择其中一个。要么从 c 程序中删除全局变量定义并将其全部放入头文件中,要么弄清楚如何正确地将头文件放入所有不同的 c 程序中。标题和程序之间的变量冲突可能是造成这种情况的原因。

【讨论】:

是的,但问题是我没有自己定义它们。我必须使用 extern "C" #include "LKH.h" #include "Genetic.h" #include "Heap.h"

以上是关于C++ 使用带有在头文件中定义的全局变量的 C 库的主要内容,如果未能解决你的问题,请参考以下文章

C语言之在头文件中定义全局变量

C 语言能不能在头文件定义全局变量?

C语言全局变量(c文件和h文件中的全局变量静态全局变量)使用注意事项

C语言全局变量(c文件和h文件中的全局变量静态全局变量)使用注意事项

能不能在头文件中定义全局变量?

C++ 怎么定义一个全局函数,能够在一个工程的所有文件中使用!