I have proto file, saying that,
message RecommendInfo{
repeated RecommendItem vec_item = 1;
}
message Response{
RecommendInfo recomInfo = 1;
}
I want to produce type Response response.
So I use following code,
Response response;
*(recommendResponse.recominfo().mutable_vec_item()) = {items.begin(), items.end()};
LOG_INFO << response.DebugString();
But there gets empty vecitem. I thought there existed Response object on stack. Response object includes RecommendInfo object on the stack. Because I want to change items inside RecommendInfo object. So I use mutable_vec_item() to set items.
I try
*(recom_response.mutable_recominfo()->mutable_vecitem()) = {items.begin(), items.end()};
The code works and print complete RecommendInfo object including vec_item.
I can't explain it clearly. When I try to change recom_response.recominfo(), it seems to be wrong. However,isn't RecommendInfo an object on stack? And I just want to modify vec_item.
Modifying vecitem modifies the RecommendInfo it belongs to.
So in order to modify the content of vecitem, you have to be operating on a modifiable (aka mutable) RecommendInfo. That's why you have to use mutable_recominfo() instead of recominfo().
Related
I am trying to initialize a server to look as specific inputs based on the request it gets. there are a lot of them so I want to initialize it with a loop as follows:
void serverInit() {
for (int i = 1; i <= qty; i++) {
String s = "/readBatt" + i;
server.on(s, runTest(i));
}
server.begin();
Serial.println("Server started.");
}
It's telling me that server.on(s, runTest(i)); is an invalid use of void expression. I know it wants it formatted as server.on(s, runTest) but the function runTest(int n) takes a parameter. How can i pass this parameter through to the function?
It seems you are using the WebServer class from the ESP32 Arduino libraries. As you have gleaned already, the callback specified in the on() method does not accept any arguments.
You have an alternative, however. You can specify a 'placeholder' in the URL path - using curly brackets - {}. In the callback, then, the corresponding argument can be retrieved by using the pathArg() method - which accepts the argument index as parameter.
Example ...
You could define your API endpoint as /readBatt/<battery number>. To configure the server to handle requests to this endpoint, then, you would use something like
#include <uri/UriBraces.h>
server.on(UriBraces("/readBatt/{}"), runTest);
In your callback, you would retrieve the first argument as follows ...
static void runTest() {
String batteryNumber = server.pathArg(0);
Serial.println("Request to read battery");
String response = "You attempted to read battery " + batteryNumber;
response += ".\nThis endpoint is a placeholder. Check again soon!";
server.send(200, "text/plain", response);
}
Finally ... Suppose your ESP8266 was running on local IP address 192.168.1.9. You could access your new API endpoint by opening
http://192.168.1.9/readBatt/1
in your browser. (Replace 1 with the relevant battery number.)
I don't think there are versions of the pathArg() which return an integer, unfortunately, so you may have to perform a conversion at some point.
You can use what's called a "closure". A closure lets you compose a function which retains access to variables outside of its scope.
A closure is written using a "lambda expression" - basically an anonymous function. C++'s syntax for lambda expressions looks like this:
[capture variable list](argument list) { body}
The capture variable list is a list of variables you want to be made available inside the body. The argument list is the normal function argument list that would get passed in by the caller. You'd write the lambda expression you need like this:
[i]() { runTest(i); }
and use it like this:
server.on(s, [i]() { runTest(i); });
To be clear, #David Collins' answer is the better way to write the web server. Using a parameter in the URL is better than creating several URLs with the parameter embedded in them. I'm just answering the question of how to pass a parameter to a function that gets called without arguments. If you write the web server code the better way, you won't need to do this (although I would do a bounds check on the value passed in the URL to make sure you're getting a valid battery number).
As the title say, I have some problem understanding what does this call return.
This is how I am using it:
fetchEngines()
{
let object = Ember.getOwner(this).lookup('application:main').engines;
console.log(object);
}
And it return me something like that:
At this point, this is what I want, the list of all my ember-engines.
But I don't know how to use it. By that I mean, how do I fetch the name of each engine, what is object at this point, I can't find anything about it.
I have tried the forEach() method, but it returns me : object.forEach is not a function. I have also tried the Object.keys method, but it returned me undefined, maybe somebody can indicate me a doc or something, I don't understand at all what is it.
Good day to you and thank you for reading.
I will answer this. This is very simple, and I made a mistake. The Object.keys method work, I didn't know how to write it well.
This is the corrected version:
fetchEngines()
{
let object = Ember.getOwner(this).lookup('application:main').engines;
// This will properly show every key in your object
console.log(Object.keys(object));
// And if you want to enumerate it
let filledArray = [];
for (let key in object) {
if (object.hasOwnProperty(key))
filledArray.push(key);
}
// The object filledArray is now a perfectly manipulable object
}
I made a ProtocolBuffer object from the proto class I usually use and I need to Serialize it. Now, I take the object and call SerializeToArray() on it like this:
int size = messageObject.ByteSize();
void* buffer = malloc(size);
messageObject.SerializeToArray(buffer, size);
As far as I know there is no problem with this since the object has data in it (I checked it by breaking right before the Serialize line).
When the method calls however it triggers an abort() which I don't know anything about.
I have no idea what it could be. The only data that is included in this object is a "type" enumerator (which I can set to the type of data that is being used in this object since it can include different sorts of messages) and it holds one message object of the repeatable type.
message MessageID
{
enum Type { LOGINDATA = 1; PLAYERDATA = 2; WORLDDATA = 3; }
// Identifies which field is filled in.
required Type type = 1;
// One of the following will be filled in.
repeated PlayerData playerData = 2;
optional WorldData worldData = 3;
optional LoginData loginData = 10;
}
This is the base message. So, Type is 2 in this case which stands for PLAYERDATA. Also, playerData is being set with a single object of the type PlayerData.
An help is appreciated.
Any time that the protobuf library aborts (which, again, should only be in debug mode or in sever circumstances), it will print information about the problem to the console. If your app doesn't have a console, you can use google::protobuf::SetLogHandler to direct the information somewhere else:
https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.common#SetLogHandler.details
typedef void LogHandler(LogLevel level, const char* filename,
int line, const std::string& message);
LogHandler* SetLogHandler(LogHandler* new_func);
The protobuf library sometimes writes warning and error messages to stderr.
These messages are primarily useful for developers, but may also help end users figure out a problem. If you would prefer that these messages be sent somewhere other than stderr, call SetLogHandler() to set your own handler. This returns the old handler. Set the handler to NULL to ignore log messages (but see also LogSilencer, below).
Obviously, SetLogHandler is not thread-safe. You should only call it at initialization time, and probably not from library code. If you simply want to suppress log messages temporarily (e.g. because you have some code that tends to trigger them frequently and you know the warnings are not important to you), use the LogSilencer class below.
The only reason for an abort that I know of (which only applies in debug builds) is if some required field isn't set. You say that the type field is set, so there must be a required field in PlayerData which is not set.
I am trying to add the instance of an object that I click on to a list on my control object. However when I do so it says that the reference is not set to an instance of an object. The code I have to instantiate the list on the control object is:
public List<Transform> selected = new List<Transform>();
And I tried to add to it to that list using this code attached to the unit:
if (!selected)
{
// Set selected state
selected = true;
// Add to Selected List
control.GetComponent<ForwardCommandScript>().selected.Add(this.transform);
// Set material colour brighter
oldColour = gameObject.renderer.material.color;
newColour = oldColour + new Color(0.2f, 0.2f, 0.2f);
gameObject.renderer.material.color = newColour;
}
I have tried with transform as well. Later I will try to remove it by finding a reference id that was set when the unit is instantiated so should I try to add the script instead of the object if I need to find its variables and then delete the game object attached to the script. I have tried with the GameObject, transform and the class. I wanted to use the class so I can easily access the variables. I have posted this on unity answers and forums but no one replied in the week it was up and I don't like reposting the same stuff on the same site.
Cheers, Scobbo
Your error NullReferenceException: Object reference not set to an instance of an object states that something in the associated line is null. Since the error message doesn't state which part is null, you have to split your code up and check which part is failing.
I'm not sure how you split it up, but try it this way:
var script = control.GetComponent<ForwardCommandScript>();
if (script == null) Debug.Log("script not found");
if (script.selected == null) Debug.Log("selected is null");
script.selected.Add(this.transform);
Now you should get one of the two messages in your debug log before the exception raises. Either the script was not found and you have to check if it is correctly assigned to the game object and if control is the correct game object, or selected is null which should not happen if you initialized it like you posted...
Thanks for adding the complete Error Message :)
you need to replace
control.GetComponent<ForwardCommandScript>().selected.Add(this.transform);
with
control.GetComponent<ForwardCommandScript>().selected.Add(transform);
because
this
is a reference to the script and not the GameObject. you could also use gameObject.transform which transform is just an abbreviation for
I need to call a function of an object and pass it a variable. Because I need to make multiple call to function of this object I've tried to make one only handler that invoke the specific function by the form value I pass it. The code works, but CFBuilder show me that there is an error (missing semicolon on the last row). I'm on Railo.
local.myReport = seoUtility.init();
local.func = form.action;
local.report = local.myReport[local.func](form.user);
So the question is: this code is correct? I could simply ignore the cfbuilder error icon?
If you don't want CFBuilder to nag you about the syntax, you can change to this:
local.myReport = seoUtility.init();
local.func = local.myReport[form.action];
local.myReport.func = local.func;
local.report = local.myReport.func(form.user);
This sets local.func to the instance of seoUtility as a reference to the actual function you want to call, preserving its relationship to the parent object. This way the offending []() syntax isn't needed.
However, this only works if seoUtility.init() is returning a fresh instance every time, as opposed to a singleton shared by the application, in which case there would be a race condition on all calls to local.myReport.func().