Reputation: 95
I'm trying to implement an array in my C++ simulation (this coding provided is to have 2 values in one network packet field).
This is my variable declaration (in the header):
Ptr<Name> m_names [2];
This is my function declaration (in the header):
void SetName (unsigned which, Ptr<Name> name);
void SetName (unsigned which, const Name &name);
Source file:
void Interest::SetName (unsigned which, Ptr<Name> name)
{
if (which < 2)
{
m_names[which] = name;
}
}
void Interest::SetName (unsigned which, const Name &name)
{
if (which < 2)
{
m_names[which] = Create<Name> (name);
}
}
The way I call this is like this (in my main file):
interest->SetName (0, nameWithSequence);
interest->SetName (1, nameWithNextSequence);
As a result, it gives an error like this:
src/ndnSIM/bindings/ns3module.cc: In function ‘PyObject* _wrap_PyNs3NdnData_SetName__0(PyNs3NdnData*, PyObject*, PyObject*, PyObject**)’:
src/ndnSIM/bindings/ns3module.cc:8418:62: error: no matching function for call to ‘ns3::ndn::Data::SetName(ns3::Ptr<ns3::ndn::Name>)’
src/ndnSIM/bindings/ns3module.cc:8418:62: note: candidates are:
./ns3/ndn-data.h:60:3: note: void ns3::ndn::Data::SetName(unsigned int, ns3::Ptr<ns3::ndn::Name>)
./ns3/ndn-data.h:60:3: note: candidate expects 2 arguments, 1 provided
The question is what is the correct way to declare the correct statement?
EDIT: I have found some of the Python definitions to bind my C++ code (SetName)
def __setattr__(self, name, value):
if name == "_interest":
return object.__setattr__ (self, name, value)
elif name == "name":
if value is None:
return self._interest.SetName (ns.ndnSIM.ndn.Name ())
elif isinstance (value, Name):
return self._interest.SetName (value._name)
elif isinstance (value, ns.ndnSIM.ndn.Name):
return self._interest.SetName (value)
elif isinstance (value, str):
return self._interest.SetName (ns.ndnSIM.ndn.Name (value))
else:
raise ValueError ("Invalid name parameter")
Upvotes: 1
Views: 409
Reputation: 29591
The error is at compile time in the Python binding code. So,
If the wrote the binding (wrapper) code yourself (using Python C API or boost::python), you must find where you define SetName binding, it is missing a parameter.
If binding is automatically generated by some tool (like SWIG or SIP), you have to find where the SetName binding is defined: this is what the wrapper tool will use to figure out what code to generate, the mistake is in that definition.
The Python code that you added to your post, setattr, indicates clearly that the self._interest.SetName(obj) calls are wrong: your C++ shows that SetName takes two parameters. If setattr is generated by some tool (ns3?) you have to find how it does this to give it the proper definition of SetName so that setattr will have proper call.
Upvotes: 0
Reputation: 1190
Okay.. let me just give you an example.
I assume Ptr
acts something like std::shared_pointer
, and Name
like a std::string
(at least for an example purposes).
First of all, i'd recommend using std::array
instead of a c-style array. But that's not really neccesary.
Second. If you plan m_names
to be an array of a fidex size, you can throw an exception when accessing to a non-existent member.
Here is some code.
Header (test.h):
#include <string>
#include <memory>
#include <array>
typedef std::shared_ptr<std::string> pString;
struct A{
protected:
static constexpr size_t array_size = 2;
std::array<pString, array_size> m_names;
static void CheckRange(size_t);
public:
void SetName(size_t id, const std::string& name);
void SetName(size_t id, const pString& name);
const std::string& GetName(size_t id) const;
const pString& GetNamePtr(size_t id) const;
};
Source:
#include "test.h"
#include <exception>
void A::SetName(size_t id, const pString &name){
CheckRange(id);
m_names[id] = name;
}
void A::SetName(size_t id, const std::string& name){
CheckRange(id);
m_names[id] = std::make_shared<std::string>(name);
}
const std::string& A::GetName(size_t id) const{
CheckRange(id);
if (!m_names[id])
throw std::logic_error("Pointer is not initialized");
return *(m_names[id].get());
}
const pString& A::GetNamePtr(size_t id) const {
CheckRange(id);
return m_names[id];
}
And here is an example of a CheckRange
function:
void A::CheckRange(size_t id){
if (!(id < array_size))
throw std::logic_error("ID should be < " +
std::to_string(array_size));
}
This code with some tests: http://ideone.com/rUvVhH
if (m_names[id])
checks if m_names[id]
contains a valid pointer (e.g. not nullptr
). I suppose Ptr
has some similar functionality.
And I believe std::make_shared<T>(...)
is similar to Create<T>(...)
.
Well, as for me, this is more or less correct way to retrieve array content :)
If something is too complicated I'll try to make it easier to understand.
You are welcomed to ask if you have any questions!
Upvotes: 0