Now, I'm studying Tensorflow Serving and try to create a Custom Servable.
So, I read the code about hashmap_source_adaptor (This is example code in Tensorflow Serving).
But, there is some code, i can't understand.
HashmapSourceAdapter::HashmapSourceAdapter(
const HashmapSourceAdapterConfig& config)
: SimpleLoaderSourceAdapter<StoragePath, Hashmap>(
[config](const StoragePath& path, std::unique_ptr<Hashmap>* hashmap) {
return LoadHashmapFromFile(path, config.format(), hashmap);
},
// Decline to supply a resource footprint estimate.
SimpleLoaderSourceAdapter<StoragePath,
Hashmap>::EstimateNoResources()) {}
HashmapSourceAdapter::~HashmapSourceAdapter() { Detach(); }
What is [config] means in line 4?
Give me a idea or hint to search about that.
The origin code is in this link. and I can't understand line 70.
https://github.com/tensorflow/serving/blob/master/tensorflow_serving/servables/hashmap/hashmap_source_adapter.cc#L70
Thanks.
The [config] is a capture list for the lambda expression. Since it's not specified otherwise, it captures config by value. This copies whatever config refers to, and makes it visible inside the lambda.
Capturing config is needed, because the code in the lambda expression uses config:
return LoadHashmapFromFile(path, config.format(), hashmap);
For config to mean something inside the lambda expression, it has to be captured. In particular, a lambda expression is basically a short-cut for creating a class. Anything in the capture list (that's actually used inside the lambda expression) becomes a parameter that's passed to the ctor for that class (and the body of the lambda expression becomes the body of an overload of operator()() for that class).
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).
I'm trying to create a simple static class library to decouple WebSocket usage from the rest of my code. Creating this will allow me to easily switch the WebSocket library (I'm currently using cpprestsdk) without the need to change my code (or its underlying logic), based on benchmark tests that will be performed in the near future.
In the below code, I'm trying to have a callback for openConnection():
class WebSocket
{
websocket_callback_client wsClient;
void openConnection(void (*ptr)(std::string response),std::string _url)
{
wsClient.connect(_url).then([](){ });
wsClient.set_message_handler([](websocket_incoming_message msg)
{
ptr(msg.extract_string().get());
});
}
};
This looks obviously wrong, as the compiler throws an error:
'ptr' is not captured
But this is what I'm trying to achieve.
How can I do this?
As the compiler says, you have not captured ptr in the lambda that is trying to use it. That is because you are setting the lambda's capture list to be empty. You need to specify ptr in the lambda's capture list:
wsClient.set_message_handler(
[ptr](websocket_incoming_message msg)
{
ptr(msg.extract_string().get());
});
Or, let the lambda figure out for itself that ptr needs to be captured:
wsClient.set_message_handler(
[=](websocket_incoming_message msg)
{
ptr(msg.extract_string().get());
});
I'm confused by the difference between V8 ObjectTemplate's Set and SetAccessor methods. My question has a simple context and 4 concrete sub-questions.
Context
Let's say I have code snippet that wants to provide a global object global to the targeting JS context. global has a property x, whose value takes int value. global also has a property log, which is a function. All the snippets are taken from V8's source, process.cc and Embedder's Guide to be precise.
HandleScope handle_scope(GetIsolate());
// Create a template for the global object where we set the
// built-in global functions.
Local<ObjectTemplate> global = ObjectTemplate::New(GetIsolate());
global->Set(String::NewFromUtf8(GetIsolate(), "log",
NewStringType::kNormal).ToLocalChecked(),
FunctionTemplate::New(GetIsolate(), LogCallback));
So this code snippet provides function log to the global. Then from the Embedder's Guide to accessors, it says
An accessor is a C++ callback that calculates and returns a value when an object property is accessed by a JavaScript script. Accessors are configured through an object template, using the SetAccessor method.
The code snippet follows:
void XGetter(Local<String> property,
const PropertyCallbackInfo<Value>& info) {
info.GetReturnValue().Set(x);
}
void XSetter(Local<String> property, Local<Value> value,
const PropertyCallbackInfo<Value>& info) {
x = value->Int32Value();
}
// YGetter/YSetter are so similar they are omitted for brevity
Local<ObjectTemplate> global_templ = ObjectTemplate::New(isolate);
global_templ->SetAccessor(String::NewFromUtf8(isolate, "x"), XGetter, XSetter);
global_templ->SetAccessor(String::NewFromUtf8(isolate, "y"), YGetter, YSetter);
Persistent<Context> context = Context::New(isolate, NULL, global_templ);
As I understand this code snippet, it's providing some integer value x to the global as the description goes.
Now,from the source of V8, I see ObjectTemplate doesn't have a Set method, instead, it's inherited from parent class Template. From Template's source code, it says:
/**
* Adds a property to each instance created by this template.
*
* The property must be defined either as a primitive value, or a template.
*/
void Set(Local<Name> name, Local<Data> value,
propertyAttribute attributes = None);
Questions
Template's Set method says it can set a primitive value to the instance of the template, then can I use Set to set x in the second code snippet instead of using SetAccessor?
If the answer to question 1 is true, then what's the difference for setting x between using SetMethod and Set? Is the difference being that any modification in JS to the property set by Set will not be reflected in C++?
If the answer to question 1 is false, then why can't I use Set on X?
From the description of accessors, it says it computes and return value. So does it mean we don't use SetAccessor to return functions? I'm confused because I mainly write JS and Haskell. Both languages spoils me to take functions as values.
Now I know it should be easy to verify all my assumptions by actually building the samples, but I have difficulties compiling the V8 source, hence I'm asking for any help.
Thank you in advanced for any effort!
1. Yes.
2. Set is the C++ equivalent (modulo property attributes) of:
Object.defineProperty(global, "x", {value: 3})
SetAccessor is the C++ equivalent of:
Object.defineProperty(global, "x", {get: function XGetter() { return ...; },
set: function XSetter(val) { ... }});
As you suggest, a consequence is that in case of Set, the C++ side has no way of knowing whether the value was changed from the JavaScript side.
3. n/a
4. The getter can return any value you want; in particular the value can be a function.
We have a business need to collect specific bindings in every JSF page. and we do that inside overridden ViewHandlerWrapper class
I use the below code inside renderView method to get the whole expression value property for every RichInputText and it's work fine for me
ValueExpression valExp = Inputcomponent.getValueExpression("value");
String ExpressionString = valExp.getExpressionString();
output was: #{binding.EmployeeId.inputValue}
When I do the same against RichButtin I got null value as following:
ValueExpression valExp = Btncomponent.getValueExpression("actionlistener");
String ExpressionString = valExp.getExpressionString();
What is the wrong in my last peace of code?
Obtaining a ValueExpression form a RichInputText works because, as the name suggests, it evaluates to a value, which may or may not be an EL expression, let alone a method.
On the other hand, a RichButton does not really have to evaluate to something; rather, it aims to invoke behavior (i.e. a method), from which you would want a MethodExpression - though in this case, the closest we get to it is a MethodBinding.
Luckily, UIXCommand, a superclass of RichButton, provides two methods from which you can obtain your action listeners:
public final MethodBinding getActionListener()
From the MethodBinding returned, you can invoke getExpressionString() so you can get what you wanted - such as some actionListener EL string like #{binding.bean.actionListenerMethod}.
public final ActionListener[] getActionListeners()
Might be worth mentioning, though there is not much merit for this in your use case. It simply returns the listeners on which you can manually process the events.
The following code works:
<cfoutput>#$.currentURL()#</cfoutput>
However, within a function, "$" is not available.
<cfscript>
function myTest() {
return $.currentURL();
}
</cfscript>
Does anyone know what actually is the equivalent of $ within a function?
Likewise, #pluginConfig.getDirectory()# works when used directly in cfoutput. However, within a cfscript function, it reports "unknown variable pluginConfig."
Thank you for advance for guiding me in the right direction.
When writing code outside the Mura Event Scope (like you do with that function), you have to obtain an instance of the Mura Scope ($) yourself. This can be done using the following code:
$ = application.serviceFactory.getBean('$');
Next you'll have to initialise the instance using an event object, a struct with value pairs or a 'siteID':
$.init(event);
$.init(myStruct);
$.init(siteID);
The same counts for the pluginConfig, this you can abtain via the Mura Scope. You'll have to pass the pluginID, moduleID, name or package of the plugin:
$.getPlugin(pluginID);
$.getPlugin(moduleID);
$.getPlugin(name);
$.getPlugin(package);
An other option you have is to pass the Mura Scope and the pluginConfig as arguments to the function. When writing a small plugin, this might be the easier way. But when writting medium or large plugins, it will get a bit messy when you're passing along these objects all the time.
The $ is used as a special framework variable in some CF frameworks (like Mura). You will need to figure out the framework context (if any) your code is executing in