Intro
This is a guide for creating a Rust DLL and calling it from C#. We will cover native return values as well as structs. This guide ...
For further actions, you may consider blocking this person and/or reporting abuse
I don't see strings as problems, i mean it was this easy to convert a c string to a rust string
then in c# it would be something like
the result is:
The rust code is thanks to this stackoverflow question
Yes but rusties don't like unsafe code ;)
That is wholly and completely untrue. We are not afraid of unsafe. There are times it is absolutely needed, and appropriate to use, and there's nothing wrong with that.
It just simply is, that a person should carefully consider whether they really need it, and if what they are doing is achievable perfectly in safe code; if they need unsafe, they should be careful to document and uphold the invariants in order to make sure things are ok and properly done.
If a person is doing ffi, it's pretty much a given that you are going to need unsafe somewhere. It comes with the territory.
Hey, thanks for the post. As you noted, the string handling is not ideal. I suggest you allocate a Box / Vec for the string, pass it to C#. From there, you just copy it into its native String type and call a Rust-defined free_string function. For users who are unexperienced with memory management / unsafety, the additional overhead seems justified for me.
Another minor I've noticed is the unideomatic return in one function (can be skipped at the end) ;)
Hey, thanks for the reply. I have a lot more experience with this now than when I wrote this. It definitely needs to be updated, i'll try and get around to it sooner than later
Any links on how to do that?
Don't have a link at hand, but I'd just return the char pointer directly (instead of storing it in a global) and ask for it again in the free function.
You should annotate the structs (on the C# side) with
[StructLayout(LayoutKind.Sequential)]
- otherwise CLR is free to reorder fields or add/remove padding which will break ABI.You're totally correct. I have that in the production code this is modeled after and I forgot it. I'll add it in, thanks!
I followed you article to bind up some common code. But got a problem whit bool always being true. Any thing special whit exposing a function using bool??
Yes, I had issues with bools as well, I didn't cover it in the article because it's weird. What I ended up doing was setting them up in c# as a byte and evaluating if it was a 1 or a 0, which SUCKS, but is totally doable. I tried getting a bunch of the marshal-as methods to work, but as of yet, none of them have. if you figure it out, let me know!
example:
rust:
c#:
Thanks, it worked. Had the solution of sending and revising a u8. But whit the byte at least i don't have to change anything on the rust side.
Some suggested to use types from libc like c_bool, but i need to get abit better at rust. Have just started out. I'll let you know if i find a good solution
I've been doing rust FFI at work for a few more months since I wrote this post. There's some things that I'll probably need to go back and update when I get the time. c_bool is a possible solution, there's also some shorthand in c# that may end up working, but I'll make sure to let you know if/when I get it working!
Thanks :-)
C# bools are Win32 BOOLs are 32-bit signed integers, for historical reasons.
Still, Marshall as book "should" work, correct?
bool on the Rust side but byte on the C# side, or (better) make a user-defined struct on the C# side, e.g. "ByteBool", that holds a single byte value and implements the conversions to/from System.Boolean.
[StructLayout(LayoutKind.Sequential)]
public struct test
{
public ByteBool isbool;
}
Did you tried to use
thread_local!
instead ofstatic mut
?Yeah. And
static mut
is pretty much almost always unneeded, since there is a safe way to do this, with interior mutability. (I'm coming from the future, but there are apis like OnceLock, LazyLock, etc)Nope, I'll look into it though. Thanks!
Hey, hope its not to late for a Question. I try your Tutorial, but i have a Problem to call a second function. It throw that he cant find an entryPoint for the second Function. Have you any Idea how i can call an another function in the same dll? Or have you maybe an Exemple?
The explicit Int32ing makes no sense. You're not being 'explicit' about the type - int is 100% always shorthand for Int32. It's as meaningless as writing Object instead of object.
What if we use fixed size char (byte) array? Would that make passing string simpler? Do you know how to do that?
I haven't done it yet, though I can think of no reason it wouldn't work. I'll see if I can throw together an example sometime today
Not sure if I should be digging up something this old, but here goes.
I wanted to send Dictionaries and Lists back and forth. What would be the best way to do something like that?
hey! Sorry I don't check this very often. I'd recommend serializing it and deserializing it. I doubt there's a good way to do it over FFI