Passing Future<int> as a function pointer to C++ using dart:ffi - flutter

I want C++ code to execute a async function Future<int> inside of C++ itself as a function pointer using dart:ffi.
C++ code have to receive int value inside of C++ itself as result of Future<int>.
Also, I cannot avoid to use Future<int> because this function is provided by method channel.
Also, passing Future<int> as function pointer means that Future<int> is invoked as callback. Thus, the function which gets int from Future<int> using await is also Future<int> and it cannot be passed as function pointer.
dart:ffi accepts normal synchronous functions as function pointer.
So I tried to convert a async function Future<int> asyncFunction() async {...} to normal function int normalFunction() {...} like runBlocking {...} of Kotlin Coroutine, but I could not find any solution.
Do you have any idea to pass a async function Future<int> to C++ code as a function pointer, or evaluate Future<int> immediately and synchronously to invoke from normal function?

Simply put, you cannot pass a Future over the FFI boundary, nor is there a way in Dart to turn an async into a sync (nothing like runBlocking), but there are a few workarounds.
The simple rule for callbacks from C to Dart is that they must be called on the Dart main thread (i.e. you can only call a callback when in a C method that is being called from Dart) and must be synchronous (i.e. you cannot return a future from Dart to C).
--- Dart call through FFI to C method -->
<-- may make a callback to Dart on same thread
So, in your case, you want a Dart callback that returns an int that you can call from C (and you must only call that when handling a Dart->C call). However, you need to make a method channel call, or something else async like calling an API over HTTP.
There are a couple of workarounds, knowing that the Dart callback method must return immediately.
You can expect the callback and already have the answer ready.
You can return an invalid value, but note what was expected. Then reissue the whole request after you've got the value ready.
Real-life example
A C cryptography library needs to determine the decryption key to decrypt a file but doesn't know the key id until it reads the file header. It takes a callback that takes a string for the key id and returns the decryption key. The problem is that, in the Dart callback, we need to call an API to exchange the key id for the decryption key, and that would be async, so not allowed.
Workarounds:
In this real life example, it was actually relatively easy to read the header of the file and find the key id(s) contained in the header. (This is, of course, the first thing the C code does too.) So, before making the call to the C decrypt function, the Dart code simply read the header, ascertained the key ids, looked them up (async/await), and put the values in memory. It could then safely call the C decrypt method, knowing that the C code would discover the same key ids, and make the callback to Dart which could satisfy the key id -> key lookup from memory.
If it had not been possible to read the header in advance the second workaround is similar, but needs two bites of the cherry. Again in this example, the callback provided the key id, but had an invalid result value which meant can't find that key. On the first method invocation, the C code finds the key id, passes that to the callback which returns the invalid response, but notes the key id in memory. The C code returns a failure to decrypt error as it was not able to obtain the key. The Dart code notes the failure and further notes that it was called-back with a previously unknown key id, which it can then go and fetch (async/await again). Having fetched the key and cached it, it can retry the original method invocation. This time the callback finds the key id / key in memory, returns it and the C code is able to decrypt and return the message.
--- Dart call to C decrypt method (1st)-->
<-- C callback to Dart passing key id
--- returns not found -->
<--- C code returns unable to decrypt
Dart code looks up missing key id (async/await) and caches
--- Dart call to C decrypt method (2nd)-->
<-- C callback to Dart passing key id
--- returns cached key -->
<--- C code returns decrypted message
So, if you can predict that the C will need a particular value, have it ready in advance, before calling the C method. Or, try it, see what it asks for on the first attempt, then get it ready and try again (assuming the C will ask for the same value it asked on the first callback).

Related

Getting unique reference to a module passed as parameter in PACT

I would like to obtain a unique key referencing a module. A unique has or the contract address would be both ok. The reason is that I want to use that string as key in a database, storing some data referenced to that token.
I am passing an interface as parameter as follows:
(defun key:string (token:module{myInterface})
; TODO
)
I've tried the hash function (hash token) but it changes on every call. Also, the describe-module function has the hash property what could be nice, but this cannot be called within a module.
I could store the hash when I load the module and pass it to the function but it is not useful because I would like to be able to call some methods in the interface.

Dart: Future<void>.then(_) requires callback with parameter

I feel like I'm probably way overthinking this... but I was working with the Flutter Camera module and wrote the following code:
controller = CameraController(camera, ResolutionPreset.medium, enableAudio: false);
controller.initialize().then((_) {});
However... This confused me, as controller.initialize() returns a Future, and the .then() requires a parameter of type void. I attempted writing the .then Future without a parameter, and I got a compilation error.
So my question is: why does the callback on completion of the Future<void> need to have a parameter at all, if the result is an empty type?
Thanks for any insight!
Actually that's because of the signature of the then method.
The then method signature looks like:
Future<R> then<R>(FutureOr<R> onValue(T value), {Function onError});
As you can see the then is expecting a callback function onValue as an argument.
The onValue callback indeed takes one argument and returns a FutureOr ( FutureOr<R> is actually a type union of R and Future, meaning the return value can either be of type R or Future).
The analysis server, analysing the code will actually expect the onValue callback to match the specified type regardless of it's argument type being a void.
Hope that helps!

I am getting an error while trying to pass the data from scoreboard to sequence, how to get rid of it?

I am new to UVM and I am trying to verify a memory design where I am trying to run a write sequence multiple times followed by read sequence same number of times so that I could read the same addresses I am writing to, and compare. For this I tried to create a new class extended from uvm_object with a queue to store the addresses I am writing to, so that I could use them in read seq and I am instantiating this class in the scoreboard and then sending the handle of class to the read sequence via uvm_config_db, now the issue is I am able to store addresses in queue but unable to get the class handle in read sequence ......Is this the right way of checking or is there some better way to check the write and read back from memory, please help me !
entire code link (yet to complete): https://www.edaplayground.com/x/3iTr
Relevant code snippets:
This is the class I created to store the addresses
class address_list extends uvm_object;
reg[7:0]addr_q[$];
function new(string name);
super.new(name);
endfunction
endclass;
In my scoreboard, I am passing the handle of class with address queue to the read sequence, here is the snippet from scoreboard
virtual function void write(mem_seq_item pkt);
if(pkt.wr_en==1)
begin
pkt_qu_write.push_back(pkt);
addr.addr_q.push_back(pkt.addr);
uvm_config_db#(address_list)::set(uvm_root::get(),"*","address",addr);
end
if(pkt.rd_en==1)
pkt_qu_read.push_back(pkt);
`uvm_info(get_type_name(),$sformatf("Adder list is
%p",addr.addr_q),UVM_LOW)
endfunction : write
In my read sequence, I am trying to get the handle
virtual task body();
repeat(3)
`uvm_do(wr_seq)
if(!uvm_config_db#(address_list)::get(this, " ", "address", addr_))
`uvm_fatal("NO_VIF",{"virtual interface must be set for:",get_full_name(),".addr_"});
`uvm_info(get_type_name(),$sformatf("ADDR IS %p",addr_),UVM_LOW)
repeat(3)
`uvm_do(rd_seq)
endtask
Error-[ICTTFC] Incompatible complex type usage
mem_sequence.sv, 137 {line where i try to get from uvm_config_db}
Incompatible complex type usage in task or function call.
The following expression is incompatible with the formal parameter of the
function. The type of the actual is 'class $unit::wr_rd_sequence', while
the
type of the formal is 'class uvm_pkg::uvm_component'. Expression: this
Source info: uvm_config_db#
(_vcs_unit__3308544630::address_list)::get(this,
" ", "address", this.addr_)
There are two problems with this line:
if(!uvm_config_db#(address_list)::get(this, " ", "address", addr_))
One is causing your error. One might lead to you not being able to find what you're looking for in the database.
This (literally this) is causing your error. You are calling get from a class derived from uvm_sequence. The first argument to get is expecting a class derived from uvm_component. Your problem is that a sequence is not part of the testbench hierarchy, so you cannot use a sequence as the first argument to a call to get (or set) in a uvm_config_db. Instead the convention is to use the sequencer that the sequence is running on, which is returned by a call to the sequence's get_sequencer() method. This solves your problem:
if(!uvm_config_db#(address_list)::get(get_sequencer(), "", "address", addr_))
This works because you used a wildcard when you called set.
Notice that I also removed the space from between the quotes. That might not give you a problem, because you used the wildcard when you called set, but in general this string should either be empty or should be a real hierarchical path. (The hierarchy input to the set and get calls is split between the first argument - a SystemVerilog hierarchical path - and the second - a string representing a hierarchical path).
uvm_config_db is basically for passing configuration between components.
For purpose of passing data from scoreboard to sequence, you can use uvm_event.
Trigger event in scoreboard using event.trigger(address_list)
sequence wait for event using event.wait_for_trigger_data(address_list)

Auto-complete a Single created from another Observable

I have a long-running operation that returns a value in code I don't control. I need that value to be published to things that ask for it. For this purpose I am using a BehaviorSubject:
var subject: Subject<Value>? = null
fun retrieveValue(): Single<Value> {
if (subject == null) {
subject = BehaviorSubject.create<Value>()
someOtherThing.retrieveValueAsync { value ->
subject.onNext(value)
}
}
return subject.singleOrError()
}
This lets me perform the operation only once and send the result as a single to all future interested parties. However, it does not work. The single will not emit a value until I call:
subject.onComplete()
But this is a problem because once the subject is completed future things can no longer subscribe to it.
What is the appropriate way to cache a value from another observable and pass it to a Single? If there was a way to have a subject automatically complete once its source observable emitted a value that would work. Single.cache() also looks promising, but I'm unsure how I would handle the fact that my value comes in asynchronously in that case.
It feels like I'm missing something silly.
There is a SingleSubject for this case.
If you don't want experimental code in your codebase, you can use ReplaySubject.createWithSize(1) and call onComplete without losing the last value, then convert it to Single.

javascript arguments are messed up when passed to NPAPI plugin function

I am using a simple NPAPI example from https://github.com/mikma/npsimple.
When I try to pass arguments from javascript to the NPAPI invoke function, the
parameters recieved by the NPAPI function are garbage, though argument count is
passed correctly. The following is the definition of the function in which I am trying to print the "args" array after converting them to char*:
invoke(NPObject* obj, NPIdentifier methodName, const NPVariant *args, uint32_t argCount, NPVariant *result)
Am I missing something here?
It is really hard to tell what you're trying to do based on what you have given us. Specifically, as smorgan requested, we need to know how you are trying to convert the args array to char*.
You are aware of how the NPVariant works? If it's a string, the NPVariant type will be NPVariantType_String and you will need to use both the UTF8Characters member of the NPString struct (which in turn is part of the NPVariant union) and the UTF8Length member, since the string may or may not be null terminated.
Also, keep in mind that depending on what you put in, it may or may not be valid to make your NPVariant a char*. If that helps, great; if it doesn't, please post the contents of the function in which you are trying to handle the input as well as the specific javascript calls that you are making. You haven't given us enough to work with to give you more than guesses as to what problem you may be having.