Iterating through Kotlin map from C native export - kotlin

We have a Kotlin package that we native build and export to C. We have the header file with all the nested struct and pinned-style pointers.
In the Kotlin code, there is a Map which we want to access. We can get a hold of the Kotlin package enum (the key of the Map), but what's the C code for actually indexing into the "kref kotlin Map object" to get to the value in the map?
Basically, we'd like to know how to manipulate Map, List and Array from C code. Actual steps and/or reference doc would be appreciated.

Kotlin/Native compiler does not export any of the collection's functions to the native library API. This decision was taken some time ago, with the idea to minimize the verbosity of the library header. However, this leads to the problem you faced. Right now, the recommended approach is to write wrapper functions in your Kotlin code.For an example of this approach, please see this ticket at the Kotlin issue tracker. I also recommend subscribing to it, to get the updates on the problem's state ASAP. Posting this in case the ticket won't be available for someone:
fun getListElement(list: List<Any?>, index: Int) = list.get(index)
/// function accessing the list element by index

Related

What is .freeze() in Kotlin/Native?

I see yet another function in Kotlin/Native, that does not exist in the Kotlin JVM or JS. What does it?
From Kotlin native's Concurrency docs
Freezing is a runtime operation making given object subgraph immutable, by modifying the object header so that future mutation attempts lead to throwing an InvalidMutabilityException. It is deep, so if an object has a pointer to another objects - transitive closure of such objects will be frozen. Freezing is the one way transformation, frozen objects cannot be unfrozen. Frozen objects have a nice property that due to their immutability, they can be freely shared between multiple workers/threads not breaking the "mutable XOR shared" invariant.
Sharing a more recent and easier explanation from Kotlin Multiplatform Mobile docs here:
The Native runtime adds an extension function freeze() to all classes.
Calling freeze() will freeze an object, and everything referenced by
the object, recursively.
Eg:
data class MoreData(val strData: String, var width: Float)
data class SomeData(val moreData: MoreData, var count: Int)
//...
val sd = SomeData(MoreData("abc", 10.0), 0)
sd.freeze()
freeze() is a one-way operation. You can't unfreeze something.
freeze() is not available in shared Kotlin code, but several libraries
provide expect and actual declarations for using it in shared code.
However, if you're using a concurrency library, like
kotlinx.coroutines, it will likely freeze data that crosses thread
boundaries automatically.
freeze is not unique to Kotlin. You can also
find it in Ruby and JavaScript.

How can I get the public elements from a Rust module?

In Node.js, I could get an array of the objects in foo with
Object.keys(require("foo"));
Is there any way I could do the same thing in Rust?
mod foo;
getobjs(foo);
No, there is no way to do this. This level of introspection of compile-time information simply doesn't exist at runtime. The concept of a module doesn't even exist.
If you are interested in compile-time information, you can do such things as build and view the docs (cargo doc --open) to see all the public items of the entire crate. You can probably also view the crate's documentation online before you use it.
There are also tools like the Rust Language Server which provide this type of information (and more) to editors and IDEs.

How can deserialization of polymorphic trait objects be added in Rust if at all?

I'm trying to solve the problem of serializing and deserializing Box<SomeTrait>. I know that in the case of a closed type hierarchy, the recommended way is to use an enum and there are no issues with their serialization, but in my case using enums is an inappropriate solution.
At first I tried to use Serde as it is the de-facto Rust serialization mechanism. Serde is capable of serializing Box<X> but not in the case when X is a trait. The Serialize trait can’t be implemented for trait objects because it has generic methods. This particular issue can be solved by using erased-serde so serialization of Box<SomeTrait> can work.
The main problem is deserialization. To deserialize polymorphic type you need to have some type marker in serialized data. This marker should be deserialized first and after that used to dynamically get the function that will return Box<SomeTrait>.
std::any::TypeId could be used as a marker type, but the main problem is how to dynamically get the deserialization function. I do not consider the option of registering a function for each polymorphic type that should be called manually during application initialization.
I know two possible ways to do it:
Languages that have runtime reflection like C# can use it to get
deserialization method.
In C++, the cereal library uses magic of static objects to register deserializer in a static map at the library initialization time.
But neither of these options is available in Rust. How can deserialization of polymorphic objects be added in Rust if at all?
This has been implemented by dtolnay.
The concept is quite clever ans is explained in the README:
How does it work?
We use the inventory crate to produce a registry of impls of your trait, which is built on the ctor crate to hook up initialization functions that insert into the registry. The first Box<dyn Trait> deserialization will perform the work of iterating the registry and building a map of tags to deserialization functions. Subsequent deserializations find the right deserialization function in that map. The erased-serde crate is also involved, to do this all in a way that does not break object safety.
To summarize, every implementation of the trait declared as [de]serializable is registered at compile-time, and this is resolved at runtime in case of [de]serialization of a trait object.
All your libraries could provide a registration routine, guarded by std::sync::Once, that register some identifier into a common static mut, but obviously your program must call them all.
I've no idea if TypeId yields consistent values across recompiles with different dependencies.
A library to do this should be possible. To create such a library, we would create a bidirectional mapping from TypeId to type name before using the library, and then use that for serialization/deserialization with a type marker. It would be possible to have a function for registering types that are not owned by your package, and to provide a macro annotation that automatically does this for types declared in your package.
If there's a way to access a type ID in a macro, that would be a good way to instrument the mapping between TypeId and type name at compile time rather than runtime.

What does "type Task x a = Task" mean in the Elm implementation of Task?

In this Github example, Task type is defined as follow:
type Task x a = Task
And then follow several functions that make use of this type.
How the Task type is supposed to be understood?
What does it mean when we define a type as:
type Foo a b = Foo
Is Task a specific case where we rely on the native javascript implementation of Task?
Is Task a specific case where we rely on the native javascript implementation of Task?
Exactly. You'll notice that Task the type but not Task the tag (thing on the right) are exported from the module, so you can't actually access the latter. It's a placeholder to make the type system happy.
Instead, the Native JavaScript implementation knows what tasks really are, which is a JS object. Any native module dealing with Tasks (either the Task module or any third-party library like elm-http) is in on the secret. However, the Task module exports a good number of helper functions that you can have a lot of control over tasks using only the already published libraries.
Clarification Edit: Yes, you need to use a third-party library to get a task that actually does some effect in the outside world. To actually run that task, you need to send it out a port; until you do that a Task is just a description of the work to do.
Seems that it's creating a kind of wild card.
In the following code:
import Html exposing (..)
type Dog a = Fido
myFunc: Dog Int -> String
myFunc myDog =
"Wouf Wouf"
main = text (myFunc Fido)
myFunc expects a Dog Int. You can then send Fido to the method.

Using managed objects in native C++ class

I want to call members of a C++/CLI class from native C++ code. Compiler is prohibiting me from doing that. I know that we can use native pointers/references in managed code but don't know way of going opposite. Can anyone help me with this by giving a simple example.Thanks in advance.
It can't be done. Memory layout of managed types is determined by the JIT, so unless your native code uses the CLR programming interface, it has no way of discovering and accessing them. Keeping references visible to the garbage collector is another problem, although overcoming that is more straightforward.
However it is possible to create native types with C++/CLI and those will have a memory layout fixed at compile time, so both managed and native code can use them. That is the way to cross the managed-native boundary in reverse. (Function pointers created from delegates are another way to cross in reverse)