-
Notifications
You must be signed in to change notification settings - Fork 224
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Accessing the super interface using interface inheritance in capnp schema #146
Comments
To upcast a capnproto-rust/capnp-rpc/test/test.rs Line 486 in 96f2f78
Notice there are no restrictions on what interface type you cast to. I.e. this doesn't only support upcasting. If you cast to something that the underlying object does not actually implement, you'll get "unimplemented" errors on method calls. There are probably a lot of ways that we could make this better, but working on this has not been high on my priority list. Another time you might want access to the base class is when you're implementing a |
Thanks for such a quick reply! With this information I was able to unblock myself. Appreciate it. |
I'm running into this problem as well. I'm trying to use https://github.com/NyanCAD/SimServer/blob/main/Simulator.capnp with this library. When using this from Python, lack of proper generics made me define concrete simulator interfaces that inherit from the generic ones. Concrete simulators use multiple inheritance to express the supported commands, like so interface Xyce extends(Simulator(Run)) { }
interface NgspiceCommands extends(Run, Tran, Op, Ac) {}
interface Ngspice extends(Simulator(NgspiceCommands)) { } In Rust I have the opposite problem, where it seems my Xyce and Ngspice client interfaces don't have any methods at all. let sim: simulator::Client<tran::Owned> = rpc_system.bootstrap(rpc_twoparty_capnp::Side::Server) This seems to be the way to instantiate a simulator supporting a single command. (I tried Would I have to do something like this every time I want to call a different command? let sim_run = simulator::Client { client: sim.clone().client }; |
The workaround suggested here currently doesn't work if the super interface has generic parameters, as As a workaround for the workaround, you can go via use capnp::capability::FromClientHook as _;
let super_interface_client = schema_capnp::super_interface::Client::new(sub_interface_client.client.hook); |
Perhaps it would make this slightly more ergonomic to provide impls of |
I think that I am running into a similar issue. I want to have one common implementation for the communication with the server that is shared across multiple sub clients. The schema looks like this:
Now, the problem is that I don't know how to start the RPC server in such a way that I can handle incoming connections from different clients (e.g., plugin-one, plugin-two). |
It's difficult to provide advice about that plugin system without seeing more about how it's intended to be used. Depending on what you're trying to accomplish, one thing that could help is having your main server interface be separated from plugins, like this: interface PluginServer {
loadPlugin @0 (pluginId : UInt64) -> (plugin : Engine.BasePlugin);
} Then the called could downcast the returned
Do you statically know the list of all plugins that you want to support? Or does the server need to dynamically support new plugins that somehow get registered at run-time? |
Thank you @dwrensha, I really appreciate your help.
The idea is that I have one server and multiple plugins that are statically known by the server. Each of these plugins use a common implementation for managing the connection to the server, but call a different 'registration' function. So, when starting a plugin, the function for handling the communication with the server from the common dependency is called with a pointer to a function of the plugin that executes the concrete 'register plugin' remote method (i.e., the plugins initiate the connection to the server to register themselves).
Yes, the server statically knows the list of supported plugins (no need to dynamically support new plugins). As the plugins implement the However, it seems that the problem is on the server side: Here, I only create a |
So it sounds like your server implements all plugin interfaces? One thing that might work is to define a new interface that extends all of the plugin interfaces: interface AllPlugins extends (PluginOne, PluginTwo) {} |
Thank you so much! That solved my problem. |
Is it still recommended practice to manually cast clients to the base interface? interface Foo {
getInt @0 () -> (i :UInt64);
}
interface Bar extends(Foo) {} a |
Nothing has changed since my previous comment #146 (comment) |
#300 made it more convenient to cast between interface client types. |
it would still be good to have a separate conversion path that is available only when the underlying client is statically known to implement |
Not sure if this is the best place to ask this question, however how exactly are we supposed to access the base interface when using interface inheritance? I've looked through the examples and the generated rust code for my interfaces but I dont see an obvious solution. Is this actually supported in the rust implementation?
The text was updated successfully, but these errors were encountered: