Warning
This post was published 41 days ago. The information described in this article may have changed.
I am trying to port a CPP DLL into Rust on Windows. A service will load the plugin dynamically and then start calling regulated functions on the plugin to exchange data and status.
I did convert some parts successfully like:
APIENTRY APIRES About(PluginInfo& info)
{
info = ExtPluginInfo;
return(RET_OK);
}
Rust equivalent:
pub const RET_OK: u32 = 0;
#[unsafe(no_mangle)]
#[allow(non_snake_case)]
pub unsafe extern "C" fn About(info: &mut PluginInfo) -> u32 {
*info = EXT_PLUGIN_INFO;
RET_OK
}
At some point, however, the server sends/receives object references! I need to interact with that reference in Rust or create and pass it to the server.
For example, when my plugin DLL gets loaded, the server calls the Create
function on that DLL. The function should provide a valid reference to a plugin class instance, which the server calls its hooks at the proper times.
// IPlugin in the header.h file
class IPlugin
{
public:
virtual APIRES Start(IServerAPI* server)=0;
virtual APIRES Stop(void)=0;
};
// main.cpp
APIENTRY APIRES Create(IPlugin** plugin)
{
if (!plugin) return(RET_ERR_PARAMS);
if (((*plugin) = new(std::nothrow) PluginInstance()) == NULL)
return(RET_ERR_MEM);
return(RET_OK);
}
// ...
class PluginInstance: public IPlugin
{
public:
APIRES Start(IServerAPI* server) {}
virtual APIRES Stop(void) {}
}
To convert this, I defined a trait reflecting the IPlugin
and a corresponding PluginInstance
struct, but it fails. How can I convert the Create
function into Rust, passing a proper value?
My try:
pub trait IPlugin {
fn Start(&mut self, server: *mut dyn IServerApi) ->ApiRes;
fn Stop(&mut self) -> ApiRes;
}
#[repr(C)]
#[derive(Clone, Default)]
pub struct MyPlugin;
impl IPlugin for MyPlugin {
fn Start(&mut self, server: *mut dyn IServerApi) -> u32 {
info!("start");
RET_OK
}
fn Stop(&mut self) -> u32 {
info!("stop");
RET_OK
}
}
#[unsafe(no_mangle)]
#[allow(non_snake_case)]
pub unsafe extern "C" fn Create(plugin: *mut *mut dyn IPlugin) -> u32 {
info!("Create");
if plugin.is_null() {
error!(" called with null plugin");
return RET_ERR_INVALID_PARAMETER;
}
let mine = Box::new(MyPlugin::default());
let mine_ptr = Box::into_raw(mine);
unsafe { *plugin = mine_ptr as *mut dyn IPlugin; }
info!("success");
MT_RET_OK
}
The "success" gets printed, but then the server throws an error when trying to call the Start
. I think the instance that I passed is not correct!
2 posts - 2 participants
🏷️ rust_feed