首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >boost中的多个定义::在Omnet++中使用kodo-rlnc的线程

boost中的多个定义::在Omnet++中使用kodo-rlnc的线程
EN

Stack Overflow用户
提问于 2017-12-13 12:43:24
回答 1查看 501关注 0票数 1

晚上好!

在使用一个名为kodo的项目期间,我的链接器告诉我几个函数的多个定义。该项目由施泰因沃夫开发,用于在中实现随机线性网络编码。make的输出引用如下:

代码语言:javascript
运行
复制
Creating executable: out/gcc-debug//simulation
./libs/boost/libboost_thread.a(once_atomic.cpp.1.o): In Funktion
`boost::thread_detail::enter_once_region(boost::once_flag&)':
once_atomic.cpp:(.text+0x0): Mehrfachdefinition von
boost::thread_detail::enter_once_region(boost::once_flag&)'
./libs/boost/libboost_thread.a(once.cpp.1.o):once.cpp:(.text+0x0): first 
efined here 
./libs/boost/libboost_thread.a(once_atomic.cpp.1.o): In Funktion
`boost::thread_detail::commit_once_region(boost::once_flag&)':
once_atomic.cpp:(.text+0x150): Mehrfachdefinition von 
boost::thread_detail::commit_once_region(boost::once_flag&)'
./libs/boost/libboost_thread.a(once.cpp.1.o):once.cpp:(.text+0x150): first defined here
./libs/boost/libboost_thread.a(once_atomic.cpp.1.o): In Funktion 
boost::thread_detail::rollback_once_region(boost::once_flag&)':
once_atomic.cpp:(.text+0x1e0): Mehrfachdefinition von 
boost::thread_detail::rollback_once_region(boost::once_flag&)'
./libs/boost/libboost_thread.a(once.cpp.1.o):once.cpp:(.text+0x1e0): first defined here
/usr/bin/ld: ./libs/gtest/libgtest.a(gtest-all.cc.1.o): undefined 
reference to symbol 'pthread_key_delete@@GLIBC_2.2.5'
//lib/x86_64-linux-gnu/libpthread.so.0: error adding symbols: DSO aus der Kommandozeile fehlt
collect2: error: ld returned 1 exit status
Makefile:111: die Regel für Ziel „out/gcc-debug//simulation“ scheiterte
make: *** [out/gcc-debug//simulation] Fehler 1

如您所见,还有几个其他的多个定义和一个无法识别的库(libgtest.a)。

kodo-rlnc从1下载并按照Steinwurf-文件的指示编译,下载自己的依赖项,也在3.中列出。

现在在我看来,boost库本身出现了故障,产生了多个定义错误。但是由于我不是C++程序员的专家,所以我可能会监督一些细节。我将在下面发布我的代码,但请注意包含-部分和Quelle::send_rlnc()函数,它使用kodo-rlnc。您会注意到,最初调用的Quelle::initialize()函数没有使用它。链接的问题发生在使用它的功能之前。(这很标准)。下面是我用包含的kodo编写的代码:

代码语言:javascript
运行
复制
#include<omnetpp.h>
#include<string.h>
#include<stdlib.h>
#include<vector>
#include<random>
#include<functional>
#include<map>
#include<iterator>
#include<algorithm>
#include<fstream>

#include <cstdint>
#include <iostream>

#include "payload_packet_m.h"

#include<kodo_core/object/file_encoder.hpp>
#include <kodo_rlnc/full_vector_codes.hpp>

#include<kodocpp/kodocpp.hpp>
#include<kodoc/kodoc.h>

using namespace omnetpp;

class Quelle : public cSimpleModule{
    private:
        //uint32_t max_symbols;
        //uint32_t max_symbol_size;

        int is_rlnc;

        std::vector<uint8_t> readFile(const char* filename);

        void send_rlnc();
        void send_lnc();
    protected:
        virtual int calculate_vector_checksum(std::vector<unsigned int> input);
        virtual void initialize() override;
        virtual void handleMessage(cMessage *msg) override;
};

Define_Module(Quelle);

std::vector<uint8_t> Quelle::readFile(const char* filename){
    std::ifstream file("testfile.txt", std::ios::binary);

    file.unsetf(std::ios::skipws);

    std::streampos fileSize;

    file.seekg(0, std::ios::end);
    fileSize = file.tellg();
    file.seekg(0, std::ios::beg);

    std::vector<uint8_t> vec;
    vec.reserve(fileSize);

    vec.insert(vec.begin(),
                std::istream_iterator<uint8_t>(file),
                std::istream_iterator<uint8_t>());

    return vec;
}

int Quelle::calculate_vector_checksum(std::vector<unsigned int> input){
    int checksum = 0;
    std::vector<unsigned int>::iterator It;
    for(It = input.begin(); It != input.end(); It++){
        checksum += *It;
    }

    return checksum;
}

void Quelle::send_rlnc(){
    uint32_t max_symbols     = 16; //par("max_symbols");
    uint32_t max_symbol_size = 1400; //par("max_symbol_size");
    fifi::api::field field = fifi::api::field::binary8;

    using rlnc_encoder  = kodo_rlnc::full_vector_encoder;
    using rlnc_decoder  = kodo_rlnc::full_vector_decoder;

    rlnc_encoder::factory encoder_factory(field, max_symbols, max_symbol_size);
    auto encoder = encoder_factory.build();

    rlnc_decoder::factory decoder_factory(field, max_symbols, max_symbol_size);
    auto decoder = decoder_factory.build();

    std::vector<uint8_t> payload(encoder->payload_size());
    std::vector<uint8_t> block_in(encoder->block_size());

    std::generate(block_in.begin(), block_in.end(), rand);

    encoder->set_const_symbols(storage::storage(block_in));

    std::vector<uint8_t> block_out(decoder->block_size());
    decoder->set_mutable_symbols(storage::storage(block_out));

    uint32_t encoded_count = 0;

    while(!decoder->is_complete()){
        uint32_t bytes_used = encoder->write_payload(payload.data());


        ++encoded_count;

        EV << "Bytes used: " << bytes_used << " Encoded count: " << encoded_count << "\n";

        payload_packet *Datenpaket= new payload_packet("Datenpaket");
        Datenpaket->setBytesArraySize(payload.size());
        Datenpaket->setData_inArraySize(block_in.size());

        uint8_t checksum = 0;

        for(unsigned int i=0; i < payload.size();i++){
            Datenpaket->setBytes(i,payload.at(i));
            checksum += payload.at(i);
        }

        for(unsigned int i=0; i < block_in.size();i++){
            Datenpaket->setData_in(i,block_in.at(i));
        }

        EV << "Packet " << encoded_count <<" payload checksum: " << (unsigned int) checksum;

        int n = gateSize("out");
        for(int i=0;i<n;i++){
            payload_packet *temp = Datenpaket->dup();
            send(temp,"out",i);
        }

        delete Datenpaket;

        decoder->read_payload(payload.data());
    }
}

void Quelle::send_lnc(){
    uint32_t max_symbols     = 16; //par("max_symbols");
    uint32_t max_symbol_size = 1400; //par("max_symbol_size");


    // std::vector<uint8_t> testvector = readFile("testfile.txt");
    // EV << "File vector size: " << testvector.size() << "\n";

    kodocpp::encoder_factory encoder_factory(
        kodocpp::codec::full_vector,
        kodocpp::field::binary8,
        max_symbols,
        max_symbol_size);

    kodocpp::encoder encoder = encoder_factory.build();

    kodocpp::decoder_factory decoder_factory(
        kodocpp::codec::full_vector,
        kodocpp::field::binary8,
        max_symbols,
        max_symbol_size);

    kodocpp::decoder decoder = decoder_factory.build();

    std::vector<uint8_t> data_out(decoder.block_size());
    decoder.set_mutable_symbols(data_out.data(), decoder.block_size());

    std::vector<uint8_t> payload(encoder.payload_size());
    std::vector<uint8_t> data_in(encoder.block_size());

    //std::vector<unsigned int> random_data(32);
    std::generate(data_in.begin(), data_in.end(), rand);
    // for(unsigned int l=0; l < data_in.size(); l++){
    //     data_in.push_back( (uint8_t) "a");
    // }

    encoder.set_const_symbols(data_in.data(),encoder.block_size());
    //EV <<"Vector checksum: " << calculate_vector_checksum(data_in) << "\n";

    uint32_t encoded_count = 0;

    while(!decoder.is_complete()){
        uint32_t bytes_used = encoder.write_payload(payload.data());

        ++encoded_count;

        EV << "Bytes used: " << bytes_used << "\n";

        payload_packet *Datenpaket= new payload_packet("Datenpaket");
        Datenpaket->setBytesArraySize(payload.size());
        Datenpaket->setData_inArraySize(data_in.size());

        uint8_t checksum = 0;

        for(unsigned int i=0; i < payload.size();i++){
            Datenpaket->setBytes(i,payload.at(i));
            checksum += payload.at(i);
        }

        for(unsigned int i=0; i < data_in.size();i++){
            Datenpaket->setData_in(i,data_in.at(i));
        }

        EV << "Packet " << encoded_count <<" payload checksum: " << (unsigned int) checksum;

        int n = gateSize("out");
        for(int i=0;i<n;i++){
            payload_packet *temp = Datenpaket->dup();
            send(temp,"out",i);
        }

        delete Datenpaket;

        decoder.read_payload(payload.data());
    }

    EV << "Ecoded " << encoded_count << " packets!" << "\n";
}

void Quelle::initialize(){
    //cMessage *msg = new cMessage("Testmessage");
    uint32_t max_symbols     = 16; //par("max_symbols");
    uint32_t max_symbol_size = 1400; //par("max_symbol_size");

    is_rlnc  = par("is_rlnc");
    EV << "RLNC: " << is_rlnc << "\n";


    // std::vector<uint8_t> testvector = readFile("testfile.txt");
    // EV << "File vector size: " << testvector.size() << "\n";

    kodocpp::encoder_factory encoder_factory(
        kodocpp::codec::full_vector,
        kodocpp::field::binary8,
        max_symbols,
        max_symbol_size);

    kodocpp::encoder encoder = encoder_factory.build();

    kodocpp::decoder_factory decoder_factory(
        kodocpp::codec::full_vector,
        kodocpp::field::binary8,
        max_symbols,
        max_symbol_size);

    kodocpp::decoder decoder = decoder_factory.build();

    std::vector<uint8_t> data_out(decoder.block_size());
    decoder.set_mutable_symbols(data_out.data(), decoder.block_size());

    std::vector<uint8_t> payload(encoder.payload_size());
    std::vector<uint8_t> data_in(encoder.block_size());

    //std::vector<unsigned int> random_data(32);
    std::generate(data_in.begin(), data_in.end(), rand);
    // for(unsigned int l=0; l < data_in.size(); l++){
    //     data_in.push_back( (uint8_t) "a");
    // }

    encoder.set_const_symbols(data_in.data(),encoder.block_size());
    //EV <<"Vector checksum: " << calculate_vector_checksum(data_in) << "\n";

    uint32_t encoded_count = 0;

    while(!decoder.is_complete()){
        uint32_t bytes_used = encoder.write_payload(payload.data());

        ++encoded_count;

        EV << "Bytes used: " << bytes_used << "\n";

        payload_packet *Datenpaket= new payload_packet("Datenpaket");
        Datenpaket->setBytesArraySize(payload.size());
        Datenpaket->setData_inArraySize(data_in.size());

        uint8_t checksum = 0;

        for(unsigned int i=0; i < payload.size();i++){
            Datenpaket->setBytes(i,payload.at(i));
            checksum += payload.at(i);
        }

        for(unsigned int i=0; i < data_in.size();i++){
            Datenpaket->setData_in(i,data_in.at(i));
        }

        EV << "Packet " << encoded_count <<" payload checksum: " << (unsigned int) checksum;

        int n = gateSize("out");
        for(int i=0;i<n;i++){
            payload_packet *temp = Datenpaket->dup();
            send(temp,"out",i);
        }

        delete Datenpaket;

        decoder.read_payload(payload.data());
    }

    EV << "Ecoded " << encoded_count << " packets!" << "\n";

    // std::vector<unsigned int> converted_values;
    //
    // for(unsigned int i=0; i < data_in.size(); i++){
    //     unsigned int temp = 0;
    //
    //     EV << "data_in Stelle " << i << ": " << (unsigned int) data_in[i] <<"\n";
    //
    //     temp = (unsigned int) data_in[i];//(data_in[i] << 8) | data_in[1];
    //
    //     EV << "Temp Stelle " << i << ": " << temp << "\n";
    //     converted_values.push_back(temp);
    // }
    //
    // EV <<"Vector checksum: " << calculate_vector_checksum(converted_values) << "\n";
    //
    // payload_packet *testpacket = new payload_packet("Testpaket");
    // testpacket->setBytesArraySize(data_in.size());
    //
    // for(unsigned int i=0; i< data_in.size();i++){
    //     testpacket->setBytes(i,data_in[i]);
    // }
    //
    // testpacket->setDaten(converted_values);
    //
    // EV << "Generated a message";
    // int n = gateSize("out");
    // for(int i=0;i<n;i++){
    //     payload_packet *temp = testpacket->dup();
    //     send(temp,"out",i);
    // }

    //delete testpacket;
}

void Quelle::handleMessage(cMessage *msg){
    //EV << "Received a message! Something is gone wrong!";
}

我确信,您在将std::vector<uint8_t> payload放入payload_paket *Datenpaket中时,已经意识到了它的可怕处理。由于某种原因,Omnet++数据包定义无法处理预定义的std::vector<uin8t_t>,因此我不得不为此声明一个数组,并将payload的内容复制到bytes数组中。但这对我的问题不重要。

是否有人知道我的代码出了什么问题,或者能给我一个提示,说明这可能不是我的错?

我很感激在这方面的任何帮助!

提前感谢!

编辑#1:

我使用Makefile来使用链接的静态库和共享库进行编译。顺序结构可以描述为:sim_folder/libs/ many_libs_in_subdirectoriessim_folder/include/ many includes in subdirectories。我的Makefile看起来如下:

代码语言:javascript
运行
复制
#
# OMNeT++/OMNEST Makefile for simulation
#
# This file was generated with the command:
#  opp_makemake -f -I./include -l libkodoc.so
#

# Name of target to be created (-o option)
TARGET = simulation$(EXE_SUFFIX)

# User interface (uncomment one) (-u option)
USERIF_LIBS = $(ALL_ENV_LIBS) # that is, $(TKENV_LIBS) $(QTENV_LIBS) $(CMDENV_LIBS)
#USERIF_LIBS = $(CMDENV_LIBS)
#USERIF_LIBS = $(TKENV_LIBS)
#USERIF_LIBS = $(QTENV_LIBS)

# C++ include paths (with -I)
INCLUDE_PATH = -I./include -I../Omnetpp/omnetpp-5.1pre2/include/omnetpp -I./include/kodo-rlnc #-I./include/platform -I./include/sak -I./include/kodo_core -I./include/fifi -I./include/storage -I./include/boost -I./include/endian -I./include/hex

# Additional object and library files to link with
EXTRA_OBJS =

# Additional libraries (-L, -l options)
#LIBS = libkodoc.so
LIBS =  libkodoc.so \
        ./libs/fifi/libfifi.a \
    ./libs/cpuid/src/cpuid/libcpuid.a \
    ./libs/gtest/libgtest.a \
    ./libs/sak/libsak.a \
    ./libs/boost/libboost_chrono.a \
    ./libs/boost/libboost_filesystem.a \
    ./libs/boost/libboost_iostreams.a \
    ./libs/boost/libboost_program_options.a \
    ./libs/boost/libboost_system.a \
    ./libs/boost/libboost_timer.a \
    ./libs/boost/libboost_thread.a \
    ./libs/gauge/src/gauge/libgauge.a \
    ./libs/tables/src/tables/libtables.a

#-L./libs/allocate -L./libs/cpuid -L./libs/fifi/ -L./libs/gtest -L./libs/kodo-core -L./libs/sak -L./libs/stub -L./libs/boost -L./libs/endian -L./libs/gauge -L./libs/hex -L./libs/platform -L./libs/storage -L./libs/tables

# Output directory
PROJECT_OUTPUT_DIR = out
PROJECTRELATIVE_PATH =
O = $(PROJECT_OUTPUT_DIR)/$(CONFIGNAME)/$(PROJECTRELATIVE_PATH)

# Object files for local .cc, .msg and .sm files
OBJS = \
    $O/eve.o \
    $O/Quelle.o \
    $O/Router.o \
    $O/Senke.o \
    $O/txc1.o \
    $O/nc_packet_m.o \
    $O/payload_packet_m.o

# Message files
MSGFILES = \
    nc_packet.msg \
    payload_packet.msg

# SM files
SMFILES =

#------------------------------------------------------------------------------

# Pull in OMNeT++ configuration (Makefile.inc)

ifneq ("$(OMNETPP_CONFIGFILE)","")
CONFIGFILE = $(OMNETPP_CONFIGFILE)
else
ifneq ("$(OMNETPP_ROOT)","")
CONFIGFILE = $(OMNETPP_ROOT)/Makefile.inc
else
CONFIGFILE = $(shell opp_configfilepath)
endif
endif

ifeq ("$(wildcard $(CONFIGFILE))","")
$(error Config file '$(CONFIGFILE)' does not exist -- add the OMNeT++ bin directory to the path so that opp_configfilepath can be found, or set the OMNETPP_CONFIGFILE variable to point to Makefile.inc)
endif

include $(CONFIGFILE)

# Simulation kernel and user interface libraries
OMNETPP_LIBS = $(OPPMAIN_LIB) $(USERIF_LIBS) $(KERNEL_LIBS) $(SYS_LIBS)

COPTS = $(CFLAGS) $(IMPORT_DEFINES)  $(INCLUDE_PATH) -I$(OMNETPP_INCL_DIR)
MSGCOPTS = $(INCLUDE_PATH)
SMCOPTS =

# we want to recompile everything if COPTS changes,
# so we store COPTS into $COPTS_FILE and have object
# files depend on it (except when "make depend" was called)
COPTS_FILE = $O/.last-copts
ifneq ("$(COPTS)","$(shell cat $(COPTS_FILE) 2>/dev/null || echo '')")
$(shell $(MKPATH) "$O" && echo "$(COPTS)" >$(COPTS_FILE))
endif

#------------------------------------------------------------------------------
# User-supplied makefile fragment(s)
# >>>
# <<<
#------------------------------------------------------------------------------

# Main target
all: $O/$(TARGET)
    $(Q)$(LN) $O/$(TARGET) .

$O/$(TARGET): $(OBJS)  $(wildcard $(EXTRA_OBJS)) Makefile $(CONFIGFILE)
    @$(MKPATH) $O
    @echo Creating executable: $@
    $(Q)$(CXX) $(LDFLAGS) -o $O/$(TARGET) $(OBJS) $(EXTRA_OBJS) $(AS_NEEDED_OFF) $(WHOLE_ARCHIVE_ON) $(LIBS) $(WHOLE_ARCHIVE_OFF) $(OMNETPP_LIBS)

.PHONY: all clean cleanall depend msgheaders smheaders

.SUFFIXES: .cc

$O/%.o: %.cc $(COPTS_FILE) | msgheaders smheaders
    @$(MKPATH) $(dir $@)
    $(qecho) "$<"
    $(Q)$(CXX) -c $(CXXFLAGS) $(COPTS) -o $@ $<

%_m.cc %_m.h: %.msg
    $(qecho) MSGC: $<
    $(Q)$(MSGC) -s _m.cc $(MSGCOPTS) $?

%_sm.cc %_sm.h: %.sm
    $(qecho) SMC: $<
    $(Q)$(SMC) -c++ -suffix cc $(SMCOPTS) $?

msgheaders: $(MSGFILES:.msg=_m.h)

smheaders: $(SMFILES:.sm=_sm.h)

clean:
    $(qecho) Cleaning...
    $(Q)-rm -rf $O
    $(Q)-rm -f simulation simulation.exe libsimulation.so libsimulation.a libsimulation.dll libsimulation.dylib
    $(Q)-rm -f ./*_m.cc ./*_m.h ./*_sm.cc ./*_sm.h

cleanall: clean
    $(Q)-rm -rf $(PROJECT_OUTPUT_DIR)

# include all dependencies
-include $(OBJS:%.o=%.d)

如您所见,我的项目中包含了几个文件(eve.cc、Router.cc、Quelle.cc .)。但唯一包括kodo-rlnc的类是我之前发布的Quelle.cc

还是谢谢你的帮助!

编辑#2

我设法通过一种快速而肮脏的方法修复了多个定义错误:我强迫once.cpp不包含该once.cpp这实际上不是一个一般性的解决办法,但它可能足以满足我的目的。但是,由于我不知道哪个库可能也需要once_atomic.cpp的功能,未来的验证是不可预测的。

现在,我仍在未定义的引用-issue中工作。

编辑#3

今天早上,我想出了如何用未定义的引用来解决这个问题。首先,我需要在链接libgtest.a时声明一个附加选项。正确的形式不是./libs/gtest/libgtest.a,而是./libs/gtest/libgtest.a -pthread。但这并没有解决整个问题:作为一个使用gcc的新手,我忘了检查链接顺序。按照这个问题中的提示,我使用-Wl,--start-group -la -lb -lc -Wl,--end-group在链接库中启用了一个循环组。

因此,随着第一个问题的脏-固定和第二个问题通常固定,我的项目开始工作。

对我来说,现在的主题是closed

但是,有没有人可以告诉我,如何以一种明确的正常方式解决第一个问题?最好不要依赖肮脏的解决方案。

谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-12-14 15:07:47

正如在编辑部分中所写的,我的问题被一个快速而肮脏的解决方案解决了。它似乎一直在运作,希望将来也是如此。

要修复once.cpponce_atomic.cpp中的多重定义,只需在boost::once_atomic.cpponce.cpp中注释once_atomic.cpp的包含。

代码语言:javascript
运行
复制
//#include "./once_atomic.cpp"

要解决第二个问题,在gtest::p线程中使用未定义的符号引用,只需要Makefile中的两个简单条目:

在LIBS中,另外声明:./libs/gtest/libgtest.a -pthread,并在LIBS周围的编译语句中添加一个循环组:

代码语言:javascript
运行
复制
$(Q)$(CXX) $(LDFLAGS) -o $O/$(TARGET) $(OBJS) $(EXTRA_OBJS) $(AS_NEEDED_OFF) $(WHOLE_ARCHIVE_ON) -Wl,--start-group $(LIBS) -Wl,--eng-group $(WHOLE_ARCHIVE_OFF) $(OMNETPP_LIBS)

这是为我做的。但也许有人能告诉我一个更好、更顺畅的解决方案!

提前感谢!

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47793346

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档