Good evening!
During the use of a project called kodo, developed by steinwurf for random linear network coding in my simulation implemented in Omnet++ (5.1pre2), my linker told me about a multiple definition of several functions. The output of make is quoted below:
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
As you can see, there are several other multiple definitions and one unrecognized library (libgtest.a).
The kodo-rlnc downloaded from 1 and compiled, following the instructions of the Steinwurf-Documentation, downloaded itself the dependencies, also listed in 3.
Now for me it looks like there's a failure in the boost-library itself, producing this multiple definition error. But since I'm not an expert C++ programmer, I may oversee some details.
I will post my code below, but keep attention at the include-section and the Quelle::send_rlnc() function, which uses the kodo-rlnc. You will notice, that it isn't used by the initially called Quelle::initialize() function. The Problem with the linking occured before using it's functionality. (This is pretty standard).
So here's my written code with the included kodo:
#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!";
}
I'm sure that you recognized the creepy handling of the std::vector<uint8_t> payload while putting it into the payload_paket *Datenpaket. For some reason the Omnet++-packet-definition can't handle a pre-defined std::vector<uin8t_t>, so I had to declare an array for this and copy the content of my payload to the bytes array. But this doesn't matter for my question.
Does somebody have an idea what is wrong with my code or can give me a hint that it may be not my fault?
I appreciate any help with this!
Thanks in advance!
EDIT #1:
I use a Makefile for the compiling process with linked static and shared libraries. The order structure can be described as: sim_folder/libs/ many_libs_in_subdirectories and sim_folder/include/ many includes in subdirectories.
My Makefile looks like this:
#
# 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)
As you can see there are several files included in my project (eve.cc, Router.cc, Quelle.cc ...). But the only class, that includes kodo-rlnc is the Quelle.cc I posted before.
Still thanks for any help!
EDIT #2
I managed to fix the multiple definition error by an quick&dirty approach: I forced the once.cpp to not include the once_atomic.cpp. This actually isn't a general fix but it may be sufficient for my purpose. But since I don't know which library may need the funtions of once_atomic.cpp too, the future proofness is unpredictable.
Now I'm still working at the undefined reference-issue.
EDIT #3
This morning I've figured out how to fix the issue with the undefined reference. First of all I needed to declare an additional option while linking the libgtest.a. Instead of ./libs/gtest/libgtest.a the correct form was ./libs/gtest/libgtest.a -pthread.
But that didn't fix the whole problem: As a newbie using the gcc, I forgot to check the linking order. Following the hint in this question I managed to enable a cycle-group within the linked libs with -Wl,--start-group -la -lb -lc -Wl,--end-group.
So with the first issue dirty-fixed and the second issue normally fixed,my project began to work.
For me the topic is closed now.
But does anybody may tell me how to fix the first issue in a clear normal way?
It would be great to not depend on a dirty solution.
Thanks!
As written in the edit sections, my problems were fixed by a quick&dirty solution. It appears to be working till now and hopefully likewise in the future.
To fix the multiple dfinition in once.cpp and once_atomic.cpp simply comment the include of the once_atomic.cpp in the once.cpp of boost::thread.
//#include "./once_atomic.cpp"
To fix the second issue with the undefined reference to a symbol within the gtest::pthread it just needed two simple entries in the Makefile:
Within the LIBS declare additionally: ./libs/gtest/libgtest.a -pthread and add a cycle group to the compile statement around the LIBS:
$(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)
This did it for me. But maybe somebody can tell me a better and smoother solution for my problems!
Thanks in advance!
Related
At first, I share my action and error reporting.
My action:
1. I added the following code to the TraCIDemo11p.cc file:
std::string edgeId ="1i";
traciVehicle->moveToXY(edgeId, 0,mobility->getCurrentPosition().x+2,mobility->getCurrentPosition().y,mobility->getAngleRad());
2. I added the following code to the TraCICommandInterface.cc file:
void TraCICommandInterface::Vehicle::moveToXY(std::string edgeId,int32_t laneid,double x,double y,double angle){
uint8_t variableId = CMD_MOVEXY;
uint8_t variableType = TYPE_COMPOUND;
int32_t count = 5;
uint8_t edgeType = TYPE_STRING;
uint8_t lanidType = TYPE_INTEGER;
uint8_t postionType = TYPE_DOUBLE;
uint8_t routeType = TYPE_BYTE;
uint8_t route = 1;
TraCIBuffer buf = connection->query(CMD_SET_VEHICLE_VARIABLE, TraCIBuffer() << variableId << nodeId << variableType <<
count <<edgeType << edgeId << lanidType << laneid << postionType << x << postionType << y <<postionType <<
angle << routeType << route );
ASSERT(buf.eof());
}
Error reporting:
Then, when I run the simulation of veins, the Traci Server gives the following error:
Error: Answered with error to command 0xc4: Wrong position in requestMessage after dispatching command. Expected command length was 61 but 59 Bytes were read.
Can anyone help me with how to solve this error?
I'm currently using Omnet++, and veins, and I have this runtime error appearing suddenly, and I am not able to understand it in order to fix it properly.
Error in module (TraCIDemoRSU11p) RSUExampleScenario.rsu[0].appl
(id=8) at event #6180, t=53.956510612297: Array of size 220 indexed by
220.
TRAPPING on the exception above, due to a debug-on-errors=true configuration option. Is your debugger ready?
I am assuming that it might be related to this message I am sending from the RSU to the vehicles with this code, but I am not sure how it's related.
cplusplus {{
#include "veins/modules/messages/WaveShortMessage_m.h"
}}
class WaveShortMessage;
message DelayedFromControllerMessage extends WaveShortMessage {
string vehiclesList [220] ;
}
I am using omnet++ Version: 5.0 and Veins 4.4
Edited, I'm using the array in these places:
1-
void TraCIDemoRSU11p::sendDelayedMessage(std::list<const char *> vehicleList) {
sentDelayedMessage = true;
//vehicleList = {};
t_channel channel = dataOnSch ? type_SCH : type_CCH;
DelayedFromControllerMessage* dsm = prepareDelayedSM("delayed",dataLengthBits, channel, dataPriority, -1,2,vehicleList);
std::list<const char *>::iterator it = vehicleList.begin();
//const char * v;
char* vx = new char [100];
vx[0] = '\0';
for(int i=0; i<vehicleList.size(); i++){
//v =*it;
strcpy(vx,*it);
//vx = *it;
++it;
dsm->setVehiclesList(i, vx);
}
if (sendDelayedEvt->isScheduled()) {
cancelAndDelete(sendDelayedEvt);
}else {
delete sendDelayedEvt;
}
sendDelayedEvt = new cMessage("delayed evt", SEND_DELAYED_EVT); // create event object to use it in timing
simtime_t offSet = dblrand() * (par("beaconInterval").doubleValue());
TimeStart = simTime() + offSet;
scheduleAt(TimeStart, sendDelayedEvt);
sendDelayedSM(dsm);
}
2-
DelayedFromControllerMessage* BaseWaveApplLayer:: prepareDelayedSM(const char * name, int lengthBits, t_channel channel, int priority, int rcvId,int serial,std::list<const char *>vehicleList ) {
DelayedFromControllerMessage* dsm = new DelayedFromControllerMessage(name);
dsm->addBitLength(headerLength);
dsm->addBitLength(lengthBits);
switch (channel) {
case type_SCH: dsm->setChannelNumber(Channels::SCH1); break; //will be rewritten at Mac1609_4 to actual Service Channel. This is just so no controlInfo is needed
case type_CCH: dsm->setChannelNumber(Channels::CCH); break;
}
dsm->setPsid(0);
dsm->setPriority(priority);
dsm->setWsmVersion(1);
dsm->setTimestamp(simTime());
dsm->setSenderAddress(myId);
dsm->setRecipientAddress(rcvId);
dsm->setSenderPos(curPosition);
dsm->setSerial(serial);
std::list<const char *>::iterator it = vehicleList.begin();
const char * v;
for(int i=0; i<vehicleList.size(); i++){
v =*it;
++it;
VLvar1.push_back(v);
dsm->setVehiclesList(i, v);
}
if ((std::string)name == "beacon") {
DBG << "Creating Beacon with Priority " << priority << " at Applayer at " << dsm->getTimestamp() << std::endl;
}
if ((std::string)name == "delayed") {
DBG << "Creating Data with Priority " << priority << " at Applayer at " << dsm->getTimestamp() << std::endl;
}
return dsm;
}
3-
void MyTraCIDemo11p::onDataDelayed(DelayedFromControllerMessage* dsm) {
int x = 0;
std::string vehichleId = mobility->getExternalId();
for (int i=0 ; i < dsm->getVehiclesListArraySize();i++)
{
vehicleList.push_back(std::string(dsm->getVehiclesList(i)));
}
ttry = std::find(vehicleList.begin(), vehicleList.end(), vehichleId);
if (vehichleId == *ttry){
x = 1;
}
if (state == QUEUING && x == 1){
findHost()->bubble("Received ");
state = WAITING;
stateToString(state);
}
}
The message should be sent from the RSU to the vehicles.
Even without seeing the actual code from the application (appl) or from the configuration file you are using, I am guessing you are trying to get the last element (element 220) from the array.
The error message already tells what the problem is. Your array has a size of 220 and you are trying to use the index 220 which is not possible, since array indexes start at 0. Therefore for addressing the last element in your array, you have to use index 221.
I am not sure if this is the reason for your error:
ttry = std::find(vehicleList.begin(), vehicleList.end(), vehichleId);
if (vehichleId == *ttry){
x = 1;
}
But, It is better to write it this way:
if (std::find(vehicleList.begin(), vehicleList.end(), vehichleId) != vehicleList.end()){
x = 1;
}
I don't recommend referencing thefind iterator (i.e., *ttry) if it is not found, it is like referencing *(vehicleList.end()).
it seems to me you have two veichleList variables, an array in the dsm and another one which is a vector. is this correct? if yes, you should make sure that the veichleList.size() is always less or equal 220.
Check this tutorial to learn how to debug your project in omnet++:
https://docs.omnetpp.org/tutorials/tictoc/part2/
So i ended up finding a solution for this issue just now.
it was by doing this:
cplusplus {{
#include "veins/modules/messages/WaveShortMessage_m.h"
}}
class WaveShortMessage;
message DelayedFromControllerMessage extends WaveShortMessage {
string vehiclesList [] ;
}
=====
DelayedFromControllerMessage* BaseWaveApplLayer:: prepareDelayedSM(const char * name, int lengthBits, t_channel channel, int priority, int rcvId,int serial,std::list<const char *>vehicleList ) {
DelayedFromControllerMessage* dsm = new DelayedFromControllerMessage(name);
dsm->addBitLength(headerLength);
dsm->addBitLength(lengthBits);
switch (channel) {
case type_SCH: dsm->setChannelNumber(Channels::SCH1); break; //will be rewritten at Mac1609_4 to actual Service Channel. This is just so no controlInfo is needed
case type_CCH: dsm->setChannelNumber(Channels::CCH); break;
}
dsm->setPsid(0);
dsm->setPriority(priority);
dsm->setWsmVersion(1);
dsm->setTimestamp(simTime());
dsm->setSenderAddress(myId);
dsm->setRecipientAddress(rcvId);
dsm->setSenderPos(curPosition);
dsm->setSerial(serial);
int NS = 0;
std::list<const char *>::iterator itPD = vehicleList.begin();
const char * vPD;
int i0 = 0;
while(itPD != vehicleList.end()){
vPD = *itPD;
++itPD;
++NS;
dsm->setVehiclesListArraySize(NS);
dsm->setVehiclesList(i0, vPD);
++i0;
VLvar1.push_back(vPD);
}
if ((std::string)name == "beacon") {
DBG << "Creating Beacon with Priority " << priority << " at Applayer at " << dsm->getTimestamp() << std::endl;
}
if ((std::string)name == "delayed") {
DBG << "Creating Data with Priority " << priority << " at Applayer at " << dsm->getTimestamp() << std::endl;
}
return dsm;
}
I removed the array size and placed with a manual counter in BaseWaveApplLayer:: prepareDelayedSM using a while loop. I thought about posting the solution to help others when facing a similar problem. :)
What is the most idiomatic way to do post-skipping? More specific I want to ensure there is no "non-skippable" (garbage) characters in my input after matching my top rule.
auto const blankOrComment
= ascii::space
| x3::lexeme ['#' >> *(x3::char_ - x3::eol) >> -x3::eol ]
;
auto const program = rule<AstProgram>("program")
= *(as<AstDefinition> (definition > ";"))
;
auto const programEntry = x3::skip(blankOrComment) [program];
One idea, I consider quite ugly was to do a separate parse call for the blankOrComment afterwards, if the main iterator position is not the end iterator. The current better idea I have is to change the root rule:
auto const programEntry = x3::skip(blankOrComment) [program >> x3::omit[*blankOrComment]];
Is there a more idiomatic way?
The simplest hack is to tack on >> eps: Live On Coliru
Note I'd strive to make the skipper more self-descriptive:
auto const skipper
= space
| '#' >> *(char_ - eol) >> (eol|eoi)
;
Likewise you can make that postskip hack more self-descriptive:
auto const post_skip = eps;
auto const program = "program" >> post_skip;
Live On Coliru
#include <iostream>
#define BOOST_SPIRIT_X3_DEBUG
#include <boost/spirit/home/x3.hpp>
namespace Parser {
namespace x3 = boost::spirit::x3;
namespace rules {
using namespace x3;
auto const skipper
= space
| '#' >> *(char_ - eol) >> (eol|eoi)
;
auto const post_skip = eps;
auto const program = "program" >> post_skip;
}
auto const programEntry = x3::skip(rules::skipper) [rules::program];
}
int main() {
using It = std::string::const_iterator;
for (std::string const input : {
"",
" program ",
"#hello\n program # comment\n",
}) {
It f = input.begin(), l = input.end();
if(parse(f, l, Parser::programEntry)) {
std::cout << "Parse success\n";
} else {
std::cout << "Parse failed\n";
}
std::cout << "Remaining: '" << std::string(f,l) << "'\n";
}
}
Prints
Parse failed
Remaining: ''
Parse success
Remaining: ''
Parse success
Remaining: ''
I'm tring create zip file with libzip library.
list<string> ListOfFiles;
ListOfFiles.push_back("file1");
ListOfFiles.push_back("file2");
ListOfFiles.push_back("file3");
...
createZip(const char* destination)
{
int err;
zip *archive = zip_open(destination, ZIP_CREATE, &err);
cout << "1. " << zip_strerror(archive) << endl;
for (list<string>::iterator iter = ListOfFiles.begin(), end = ListOfFiles.end(); iter != end; iter++)
{
zip_source *source = zip_source_file(archive,iter->c_str(),0,0);
cout << "2. " << zip_strerror(archive) << endl;
index = zip_file_add(archive, iter->c_str(), source, ZIP_FL_OVERWRITE);
cout << "3. " << zip_strerror(archive) << endl;
}
zip_close(archive);
cout << "4. " << zip_strerror(archive) << endl;
}
output:
No error
No error
Invalid argument ...
Read error: No such file or directory
When I tried create zip, error value return "Invalid argument" after i tried added file to zip.
For further help here is my code that worked for me.
int main() {
int err = 0;
ifstream fs, fs1;
fs.open("my_test.txt", std::ios::binary);
fs1.open("f 2.pdf", std::ios::binary);
std::string content((std::istreambuf_iterator<char>(fs)), (std::istreambuf_iterator<char>()));
std::string content1((std::istreambuf_iterator<char>(fs1)), (std::istreambuf_iterator<char>()));
zip* z = zip_open("foo.zip", ZIP_CREATE, &err);
zip_source_t* zs;
zs = zip_source_buffer(z, content.c_str(), content.length(), 0);
zip_file_add(z, "test.txt", zs, ZIP_FL_OVERWRITE | ZIP_FL_ENC_UTF_8);
zs = zip_source_buffer(z, content1.c_str(), content1.length(), 0);
zip_file_add(z, "test.pdf", zs, ZIP_FL_OVERWRITE | ZIP_FL_ENC_UTF_8);
zip_close(z);}
i opened 2 files (one txt and one pdf) in binary mode and read the entire files. I have store its data to two string contents. Next i have created the zip file (foo.zip), Next step is to create the source buffer. first argument is the zip file second is the content the third is the length of the content to be written. finally we add the buffer inside the zip. BE CAREFUL the zip_file_add creates new file with the name provided (my_test.txt-> text.txt and f 2.pdf -> test.pdf)
Is there any way to get clang::SourceLocation for every #include in file by its clang::FileID or clang::FileEntry or something?
What about using source manager's GetIncludedLoc function which takes fileid as parameter.
SourceManager.GetIncludedLoc(fileid)
Thank's #Hemant for your answer, you're right
I Already found that by myself (in clang 3.8 it is called getIncludeLoc)
but forgot to write here.
I used this to find the location after all #includes where i can put my own.
Here's the function (For sure not the best way) I wrote for this, hope it helps someone
SourceLocation getIncludeLocation(FileID fileID, SourceManager &sm, unsigned carriages) {
return SourceLocation();
set<unsigned> lines;
if (fileID.isInvalid())
for (auto it = sm.fileinfo_begin(); it != sm.fileinfo_end(); it++) {
SourceLocation includeLoc = sm.getIncludeLoc(sm.translateFile(it->first));
if (includeLoc.isValid() && sm.isInFileID(includeLoc, fileID)) {
lines.insert(sm.getSpellingLineNumber(includeLoc));
}
}
unsigned pos(0);
if (!lines.empty()) {
bool first = true;
for (unsigned line :lines) {
if (first)
first = false;
else if ((line - pos) > carriages)
break;
pos = line;
//cout << "Include line:" << pos << endl;
}
//cout << console_hline('-') << endl;
}
cout << sm.getFileEntryForID(fileID)->getName() << endl;
return sm.translateFileLineCol(sm.getFileEntryForID(fileID), ++pos, 1);
}
Also some information about includes can be get by
Preprocessor::GetIncludeFilenameSpelling(SourceLocation Loc, StringRef &Buffer)
and
Lexer::ComputePreamble(StringRef Buffer, const LangOptions &LangOpts, unsigned MaxLines = 0)