
Allowing Matlab to Talk to Rust - smitec
http://smitec.io/2016/02/04/allowing-matlab-to-talk-to-rust.html
======
jblazevic
Great stuff!

One minor suggestion, completely beside the point so please forgive me: a
safer and perhaps more idiomatic way to implement the multiply_safe function
would be with a functional-style one-liner:

    
    
        fn multiply_safe(a : Vec<f64>, b : Vec<f64>) -> Vec<f64> {
            if a.len() != b.len() {
                panic!("The two vectors differ in length!");
            }
            return a.iter().zip(b.iter()).map(|(x, y)| x * y).collect()
        }
    

Safer because you don't manipulate indices and lengths directly like you would
in C, so there is no opportunity of an off-by-one bug or things like that.
Surprisingly, rustc optimizer makes sure that this performs as well as the
index-wrangling implementation (according to some simple tests I just ran).

~~~
masklinn
There are plenty of other things to improve/rustify.

* The function should take slices as inputs for instance, that way not only doesn't it take ownership of the inputs you don't need to copy the C arrays to vecs in the C-exposed function, you can just convert them to slice (which is essentially 0-cost, you just create a std::raw::Slice on the stack)

* The function also shouldn't panic it should return a Result (or an Option)

* Maybe less rustic but more efficient would be to take the output as an &mut [f64] (as the extern function does), that way the whole thing can be allocation-free

1 and 3 also simplify the glue code, instead of having to copy data from the
input _f64 to brand new vecs and from the output vec to the output_ f64, just
convert the three input pointers with from_raw_parts and from_raw_parts_mut.
That makes for much simpler and easier to review unsafe code as well:

    
    
        let a = unsafe { from_raw_parts(a_double, elements) };
        let b = unsafe { from_raw_parts(b_double, elements) };
        let c = unsafe { from_raw_parts_mut(c_double, elements) };
    

that's it, no mucking around with pointer offsets, and the rest if safe Rust.

Something like this: [http://is.gd/uFhx2J](http://is.gd/uFhx2J)

------
ampron
Well explained! Here are some more examples using the calllib function to
access the rust code, although I think the mex interface is probably the
better way to go.
[https://github.com/ampron/rustlab](https://github.com/ampron/rustlab)

~~~
smitec
awesome! thanks. I hadn't seen calllib before. Nice to see someone else in the
overlap of matlab users and rust users.

------
marmaduke
Interesting, though the C middleman isn't necessary if you can describe to
Rust's FFI that mxArray is an opaque struct (I imagine the other regular
functions in the MEX API are cakewalk for an FFI worth it's weight).

A while ago I wrote a mexFunction purely in Cython, and it was wondeful
because Python was immediately available to work with (instead of C). The
problem was that the numerical libraries on which NumPy builds often shared
symbol names with MATLAB (such as svd, or hdf5) that differ in implementation
resulting segfaults or corrupted data.

~~~
marmaduke
For the non-MATLABers, a mex function is just a small shared library which
exports a single function 'mexFunction'. It's dynamically loaded by MATLAB
when called in the MATLAB language.

------
bluejekyll
One thing that jumped out to me, and I haven't worked with Rust FFI enough to
know this answer. Is the C library necessary? Since Rust is exporting the C
interfaces directly, couldn't Matlab link directly against that?

~~~
masklinn
It would also require generating the Matlab bindings for Rust, but more
problematically it seems to use a special compiler/linker (`mex`). I don't
know if that does genuine work of if it's just a wrapper/synchronizer around
compilers and linkers which you could do without.

~~~
dsharlet
The main thing mex does is let you link to the matlab API libraries that are
otherwise hard to get. To work around this, I like to just grab the API
directly from the calling process via dlsym/GetProcAddress. That way, you can
build mex libraries with any toolchain you want, even without matlab
installed.

~~~
marmaduke
This can be non-portable because the mex header will expand certain function
calls to specific implementations depending on the mex options you use. I seem
to recall e.g. mxGetM expanded to mxGetM700 in one version.

