OMNET++ how to access function or variables in another class - omnet++

I have modified inet NodeStatus.cc with a customized function that return the variable value as follows:
int NodeStatus::getValueA()
{
return ValueA;
}
Then, I created another simple module called simpleNodeB.cc and I wanted to retrieve ValueA from NodeStatus.cc. I tried the following code in simpleNodeB.cc but didn't work:
if(getParentModule()->getSubModule(NodeStatus).getValueA()==test1)
bubble("Value is the same");
The error message I got -> error: expected expected primary-expression before ')' token. I'm not sure if I used the correct way to call getValueA() function. Please enlighten me. thanks a lot.

There are many errors in your code.
The method getSubmodule requires a name of module, not a name of class. Look at your NED file and check the actual name of this module.
getSubmodule returns a pointer to the cModule object. It has to be manually cast into another class.
Assuming that an NodeStatus module in your NED is named fooStatus the correct code should look like:
cModule *mod = getParentModule()->getSubmodule("fooStatus");
NodeStatus *status = check_and_cast<NodeStatus*>(mod);
if(status->getValueA() == test1)
bubble("Value is the same");
Reference: OMNeT++ Manual.

Related

Code explanation of the json11 library about implicit constructor

I'm reading the source code of the main json11 header file.
It contains the following declaration:
template <class T, class = decltype(&T::to_json)>
Json(const T & t) : Json(t.to_json()) {}
I'm trying to find some documentation about this usage of decltype and class inside a template declaration but no success.
Does this construction/usage has a name in C++? Any good reference about it?
It's using SFINAE ("Substitution Failure Is Not An Error"), a common technique for advanced template stuff. In this case, it's used as a crude(1) test whether the type T has a function named to_json.
How it works: if the expression T::to_json is well-formed (there is something named to_json inside the type T), decltype(T::to_json) denotes a valid type and the constructor template can be used normally.
However, if T::to_json is ill-formed (i.e. if there is no to_json member inside T), it means substituting the template argument for T has failed. Per SFINAE, this is not an error of the entire program; it just means that the template is removed from further consideration (as if it was never part of the class).
The effect is thus that if type T has a member to_json, you can use an object of type T to initialise a Json object. If there is no such member in T, the constructor will not exist.
(1) I'm saying crude test because this only checks that T has such a member. It doesn't check that the member is a function which can be invoked without arguments and returns something another constructor of Json can accept. A tighter-fitting test might look something like this:
template <class T, class = std::enable_if_t<std::is_constructible<Json, decltype(std::declval<const T>().to_json())>::value>>
Json(const T & t) : Json(t.to_json()) {}
[Live example]

omnetpp: reading module parameters

I have the following module defined in a ned file:
#namespace(cbsdsim);
simple SASSim {
parameters:
#class(SASSim);
int maxCbsdsPerSas = 10;
}
I create the module by calling the following (from another module):
cModuleType* sasSimModType = cModuleType::find("SASSim");
sasSimModType->setName("SASSim");
char* name = "SAS.1";
SASSim* sasSimMod = (SASSim*) sasSimModType->create(name,parent);
The constructor for SASSim gets called. Here is the constructor:
SASSim::SASSim() {
cout << " SASSim::SASSim" << endl;
//this->finalizeParameters();
int cbsdFanIn = par("maxCbsdPerSas");
.....
}
However omnetpp is unhappy about calling par(...) in the code fragment above. I get an exception and a confusing error message:
what(): (omnetpp::cModule): Object has no associated cComponentType (maybe omnetpp::cModule is not derived from cModule/cChannel?)
Indeed when I add this->getNumParams() in the constructor it returns 0. If I hard code the parameter, the initialization works fine so I assume I need to do something in order to load the parameters. I could, presumably put the parameters in omnetpp.ini or elsewhere but I would like to know why this does not work.Do I have to do something prior to calling create to load the params? Thanks,
You can only access the parameters after initialization - not in the constructor of the Module. This is a bit strange because creating cGates etc. works fine from the constructor.

Swift: error: use of instance member on type

I'm trying to build a swift script but I got stuck with this error:
./1.swift:10:11: error: use of instance member 'thisIsmyFunction' on type 'myScript'; did you mean to use a value of type 'myScript' instead?
myScript.thisIsmyFunction()
~~~~~~~~ ^
Here is my code:
#!/usr/bin/swift
import Foundation
class myScript {
func thisIsmyFunction() {
print("Do something in there!")
}
}
myScript.thisIsmyFunction()
What I'm trying to do is access to the function and execute the print.
Any of you knows what I'm doing wrong?
I'll really appreciate your help.
You can only call an instance method on an instance of a class. For example, you would have to create an instance of myScript, then call it:
let script = myScript()
script.thisIsmyFunction()
You can also choose to make thisIsmyFunction a class method (which is formally known as a "type method" in Swift), and call it like the way you are doing right now:
class func thisIsmyFunction() {...}
Note the class modifier in front of func. Of course, this means you can't access self inside the function, because there is no longer an instance of the class.
For more information, see the Swift documentation on methods.
Aside: Swift classes should start with capital letters.

Function parameter error - Missing Argument Label Anomaly - SWIFT

I have a strange issue (which I can overcome however I would like to get a proper understanding of my error).
I have a small random number generator function which I use often:
func ranNum(low: Int, high:Int) -> UInt32 {
var result = arc4random_uniform(UInt32((high+1)-low)) + low
return result
}
When I use this in XCode playgrounds it works just fine if I pass in something like:
ranNum(1, 10)
However, in a regular Swift file it generates the error message : Missing argument label 'hi:' in call. Now I can overcome this by calling the function this way:
ranNum(1, hi:10)
Apart from it just being a little harder to read, it just isn't making sense why it works in Playgrounds but also why it requires only the 2nd argument label and not both. Any help as to what I am not understandinh would be greatly appreciated.
That's called external parameter name, and by default:
global functions: don't have implicit external names
class/struct methods: external names are automatically defined for all parameters after the first
initializers: external names are automatically defined for all parameters
If not explicitly specified, external names take the same name as the local parameter.
You can override that by prefixing a local parameter name with _. In your case:
func ranNum(low: Int, _ high:Int) -> UInt32 {
...
}
You mentioned that in playground calling the function works without any external parameter name - I may argue that:
in playground you have that function as a global function
in other tests, that function is a class/struct method
Am I right?

How to (if possible) get the reference of an in-memory object (class instance)?

I'm trying to see if there's a way to get a refference of an object which is outside the local (and global) scope, but who exists in memory.
Let's say in my program, i've instantiated an object whose reference is this:
{O:9*\PROGRAM=ZAVG_DELETE_THIS\CLASS=LCL_SMTH}
Far away after tons of calls, in a context where i wouldn't be able to access this object, could i do something like getting the reference of this object simply by knowing the above string?
I was looking into the cl_abap_*descr classes, but i haven't found a method that takes the 'program_name', 'class_name' and 'instance_number', to return the reference of an object.
I'm trying to do this for the purpose of debugging, not to build something that works.
[EDIT 1]:
I assumed that the o:9 string was required in order to get the reference of the object. As pointed out in the response of #mydoghasworms, this isn't the case. It seems that i only need the local name of the variable which holds the reference.
I hope I understand your question correctly, because I am not sure what you mean with "for the purpose of debugging", but here goes:
You can access the variables of another program that are loaded in the memory of the same session (I am pretty sure it does not need to be in the call stack) using:
ASSIGN ('(PROGRAM)VARIABLE') TO LV_LOCAL.
With reference variables, it becomes a bit more tricky, but here is an example that will help to demonstrate.
Here is our calling program that contains a reference variable LR_TEST which we want to access somewhere else. For the purpose of the demonstration, I make reference to a locally defined class (because that's what I gather from your question).
REPORT ZCALLER.
class lcl_test definition.
public section.
data: myval type i.
methods: my_meth exporting e_val type i.
endclass.
data: lr_test type ref to lcl_test.
CREATE OBJECT lr_test.
lr_test->MYVAL = 22.
perform call_me(zcallee).
class lcl_test implementation.
method my_meth.
* Export the attribute myval as param e_val.
e_val = myval.
endmethod.
endclass.
Here is the program in which we want to access a variable from the above program.
REPORT ZCALLEE.
form call_me.
field-symbols: <ref>.
data: ld_test type ref to object.
data: lv_val type i.
* Exhibit A: Gettinf a reference to a 'foreign' object instance
assign ('(ZCALLER)LR_TEST') to <ref>.
* <ref> now contains a reference to the class instance from the program
* ZCALLER (not very useful, except for passing around maybe)
* Exhibit B: Getting a public attribute from a 'foreign' class instance
assign ('(ZCALLER)LR_TEST->MYVAL') to <ref>.
* <ref> now contains the value of the attribute MYVAL
* Exhibit C: Getting a reference to an instance and calling a method
assign ('(ZCALLER)LR_TEST') to <ref>. "Again the class reference
if sy-subrc = 0. "Rule: Always check sy-subrc after assign before
"accessing a field symbol! (but you know that)
ld_test = <ref>. "Now we have a concrete handle
* Now we make a dynamic method call using our instance handle
CALL METHOD ld_test->('MY_METH')
IMPORTING
e_val = lv_val.
endif.
endform.

Resources