Coder Social home page Coder Social logo

ubolonton / emacs-module-rs Goto Github PK

View Code? Open in Web Editor NEW
334.0 334.0 22.0 640 KB

Rust binding and tools for Emacs's dynamic modules

Rust 84.59% Shell 1.20% Emacs Lisp 8.41% PowerShell 1.39% CSS 0.13% JavaScript 0.49% C++ 3.79%
binding emacs emacs-modules ffi rust

emacs-module-rs's People

Contributors

aeronotix avatar cireu avatar jjpe avatar nwjsmith avatar ubolonton avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

emacs-module-rs's Issues

[emacs_module] 'unexpected close delimiter'

I am using a plugin for nvim that leverages this library. When I try to run cargo build --release, it fails on the emacs_module build step:

   Compiling emacs_module v0.10.0
error: unexpected close delimiter: `]`
   --> <...>/.local/share/nvim/plugged/parinfer-rust/target/release/build/emacs_module-9fb3f11fcc6e3c12/out/emacs_module.rs:112:40
    |
112 | # [ derive ( Copy , Clone ) ]; 16usize ] , }# [ test ]
    |                                        ^ unexpected close delimiter

error: aborting due to previous error

error: Could not compile `emacs_module`.
warning: build failed, waiting for other jobs to finish...
error: build failed

Looking at the library cargo.toml file, it looks like the latest version is supplied:

emacs = "0.11.0"

I haven't seen any other issues about this, so I am wondering if there is some problem specific to my setup?

Need some help getting started

I am just getting started with rust and since I am coming from elisp I figured this would be a good place to get started. Unfortunately I am not even able to begin building the greeting example, things already fail when trying to build emacs:

$ cargo build                                                                              
   Compiling emacs v0.12.3                                                                     
error[E0425]: cannot find function `type_name` in module `any`                                 
  --> /home/jonas/.cargo/registry/src/github.com-1ecc6299db9ec823/emacs-0.12.3/src/types/us    er_ptr.rs:52:14                                                                                
   |                                                                                           
52 |         any::type_name::<Self>()                                                          
   |              ^^^^^^^^^ not found in `any`                                                 
help: possible candidates are found in other modules, you can import them into scope           
   |                                                                                           
1  | use core::intrinsics::type_name;                                                          
   |                                                                                           
1  | use std::intrinsics::type_name;                                                           
   |                                                                                           
                                                                                               
error[E0658]: use of unstable library feature 'maybe_uninit' (see issue #53491)                
 --> /home/jonas/.cargo/registry/src/github.com-1ecc6299db9ec823/emacs-0.12.3/src/error.rs:    4:5                                                                                            
  |                                                                                            
4 | use std::mem::MaybeUninit;                                                                 
  |     ^^^^^^^^^^^^^^^^^^^^^                                                                  
                                                                                               
error[E0658]: use of unstable library feature 'maybe_uninit' (see issue #53491)                
   --> /home/jonas/.cargo/registry/src/github.com-1ecc6299db9ec823/emacs-0.12.3/src/error.r    s:111:26                                                                                       
    |                                                                                          
111 |         let mut symbol = MaybeUninit::uninit();                                          
    |                          ^^^^^^^^^^^^^^^^^^^                                             
                                                                                               
error[E0658]: use of unstable library feature 'maybe_uninit' (see issue #53491)                
   --> /home/jonas/.cargo/registry/src/github.com-1ecc6299db9ec823/emacs-0.12.3/src/error.r    s:112:24                                                                                       
    |                                                                                          
112 |         let mut data = MaybeUninit::uninit();                                            
    |                        ^^^^^^^^^^^^^^^^^^^                                               
                                                                                               
error[E0658]: use of unstable library feature 'maybe_uninit' (see issue #53491)                
   --> /home/jonas/.cargo/registry/src/github.com-1ecc6299db9ec823/emacs-0.12.3/src/error.r    s:218:22                                                                                       
    |                                                                                          
218 |         symbol: &mut MaybeUninit<emacs_value>,                                           
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^                                            
                                                                                               
error[E0658]: use of unstable library feature 'maybe_uninit' (see issue #53491)                
   --> /home/jonas/.cargo/registry/src/github.com-1ecc6299db9ec823/emacs-0.12.3/src/error.r    s:219:20                                                                                       
    |                                                                                          
219 |         data: &mut MaybeUninit<emacs_value>,                                             
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^                                              
                                                                                               
error[E0599]: no function or associated item named `uninit` found for type `std::mem::Maybe    Uninit<_>` in the current scope                                                                
   --> /home/jonas/.cargo/registry/src/github.com-1ecc6299db9ec823/emacs-0.12.3/src/error.r    s:111:39                                                                                       
    |
111 |         let mut symbol = MaybeUninit::uninit();
    |                          -------------^^^^^^
    |                          |
    |                          function or associated item not found in `std::mem::MaybeUninit<_>`

error[E0599]: no function or associated item named `uninit` found for type `std::mem::MaybeUninit<_>` in the current scope
   --> /home/jonas/.cargo/registry/src/github.com-1ecc6299db9ec823/emacs-0.12.3/src/error.rs:112:37
    |
112 |         let mut data = MaybeUninit::uninit();
    |                        -------------^^^^^^
    |                        |
    |                        function or associated item not found in `std::mem::MaybeUninit<_>`

error[E0599]: no method named `assume_init` found for type `std::mem::MaybeUninit<*mut emacs_module::emacs_value_tag>` in the current scope
   --> /home/jonas/.cargo/registry/src/github.com-1ecc6299db9ec823/emacs-0.12.3/src/error.rs:120:60
    |
120 |                     symbol: unsafe { TempValue::new(symbol.assume_init()) },
    |                                                            ^^^^^^^^^^^

error[E0599]: no method named `assume_init` found for type `std::mem::MaybeUninit<*mut emacs_module::emacs_value_tag>` in the current scope
   --> /home/jonas/.cargo/registry/src/github.com-1ecc6299db9ec823/emacs-0.12.3/src/error.rs:121:56
    |
121 |                     data: unsafe { TempValue::new(data.assume_init()) },
    |                                                        ^^^^^^^^^^^

error[E0599]: no method named `assume_init` found for type `std::mem::MaybeUninit<*mut emacs_module::emacs_value_tag>` in the current scope
   --> /home/jonas/.cargo/registry/src/github.com-1ecc6299db9ec823/emacs-0.12.3/src/error.rs:128:54
    |
128 |                     tag: unsafe { TempValue::new(tag.assume_init()) },
    |                                                      ^^^^^^^^^^^

error[E0599]: no method named `assume_init` found for type `std::mem::MaybeUninit<*mut emacs_module::emacs_value_tag>` in the current scope
   --> /home/jonas/.cargo/registry/src/github.com-1ecc6299db9ec823/emacs-0.12.3/src/error.rs:129:58
    |
129 |                     value: unsafe { TempValue::new(value.assume_init()) },
    |                                                          ^^^^^^^^^^^

error[E0658]: use of unstable library feature 'maybe_uninit' (see issue #53491)
   --> /home/jonas/.cargo/registry/src/github.com-1ecc6299db9ec823/emacs-0.12.3/src/error.rs:222:67
    |
222 |         unsafe_raw_call_no_exit!(self, non_local_exit_get, symbol.as_mut_ptr(), data.as_mut_ptr())
    |                                                                   ^^^^^^^^^^

error[E0658]: use of unstable library feature 'maybe_uninit' (see issue #53491)
   --> /home/jonas/.cargo/registry/src/github.com-1ecc6299db9ec823/emacs-0.12.3/src/error.rs:222:86
    |
222 |         unsafe_raw_call_no_exit!(self, non_local_exit_get, symbol.as_mut_ptr(), data.as_mut_ptr())
    |                                                                                      ^^^^^^^^^^

error: aborting due to 14 previous errors

Some errors occurred: E0425, E0599, E0658.
For more information about an error, try `rustc --explain E0425`.
error: Could not compile `emacs`.

To learn more, run the command again with --verbose.

I am such a beginner I have no idea yet how to proceed. Could you please help me out?

If I try to build the emacs-module-rs directly I get the same errors, prefixed with some warnings:

$ bin/build 
warning: couldn't execute `llvm-config --prefix` (error: No such file or directory (os error 2))
warning: set the LLVM_CONFIG_PATH environment variable to a valid `llvm-config` executable
   Compiling emacs v0.12.3 (/home/jonas/git/pep/emacs-module/emacs-module-rs)
error[E0425]: cannot find function `type_name` in module `any`
  --> src/types/user_ptr.rs:52:14
...

How to call Elisp functions from a backgroud thread?

I wannt to start a new thread and then call Elisp functions within that thread, but I found that Env does not implement Sync or Send. So is there anyway to archive my goal? Thanks.

More information about my use case:
I'd like to start a subprocess and read repeatedly its output in a loop in a thread, after reading in some data, I'll call a Elisp function to tell Emacs.

[discussion] Is it possible to pass a hashmap from Emacs to Rust?

I'm working on a package that's passing a hashmap serialized as JSON back and forth between my rust library and Emacs. Unfortunately, this can be a pretty slow processes on large JSON objects. I was wondering if it's possible to pass in and return an Emacs hashmap directly?

Or are there alternative approaches for emulating a hashmap? Should I do something akin to this: https://github.com/ubolonton/emacs-module-rs/blob/master/test-module/src/hash_map.rs

Integration with `help-fns` and `find-func`

  • Signature should use argument names defined in Rust, instead of ARG1, ARG2, like currently. This can be done by either:
    • Using advertised-signature-table.
    • Adding usage: to the end of the docstring.
  • find-function should be able to find the correct location in Rust source.
    • Source files should be packaged together with the dylib (e.g. in a tar archive).
    • The dylib should contain more metadata for each exported function.

[discussion] writing json parser as rust module

Thanks for your work on this package!

I am working on lsp-mode which at this stage of the project has issues with the performance of json parsing and I am investigating what are the options to implement it as a Rust emacs module and the potential optimization effect. I am rust beginner and in general, I do not have a lot of low-level programming knowledge and I have few questions regarding whether the whole approach will make sense.
Generally, do you think this approach is feasible? I know that the json parsing will be very fast in rust, but what about the code that will convert from rust data structures to emacs one? Do you think that running it in a separate thread and then reporting it to the emacs-lsp thread will work in case we want to parse several responses in parallel (e. g. using a thread pool to create async parse json function)?

How to call other methods of emacs env?

There are other functions defined in emacs-module.h such as vec_get vec_size. How to call these method?

Or would you like to impl trait FromLisp for Vec?

Expose environment function should_quit

This is useful to check if the user pressed C-g during a long running computation. From the documentation:

If your module includes potentially long-running code, it is a good
idea to check from time to time in that code whether the user wants to
quit, e.g., by typing ‘C-g’ (*note Quitting::). The following function,
which is available since Emacs 26.1, is provided for that purpose.

-- Function: bool should_quit (emacs_env *ENV)
This function returns ‘true’ if the user wants to quit. In that
case, we recommend that your module function aborts any on-going
processing and returns as soon as possible.

Notice that this is only available since Emacs 26.1, so some runtime check for the Emacs version would probably be needed.

Some confusion regarding the live-reload workflow

Hi, I'm trying to write some elisp bindings to a rust library and would like to benefit from live reloading.

Looking at the workflow shown in magit-libgit2, I've:

  • Copied bin/load.sh and modified the file names for my project
  • Added emacs-rs-module to my dev dependencies
  • Tried to run the script using cargo-watch as shown in the aforementioned project's readme

But it doesn't seem to work - find "$root" -iname "*emacs_rs_module*.$ext" returns nothing.

Furthermore, I can't find any file that looks like *emacs_rs_module*.so anywhere in my project (after a build of course).

Is this workflow just broken at the moment?

Maybe some build script machinery could be used to have a more ergonomic workflow?
I'm not sure I know enough about how emacs (and linux I guess) loads dynamic libraries to work on it myself, but I feel like it could possibly make this a bit more ergonomic (e.g. automate the whole .so/.dylib symlinking thing, generate elisp files that modify the load path and require the module).

`FromLisp` for `Vec`?

Hi there, this is a really cool library and I'm excited to speed up my Emacs with Rust.

I'm having trouble figuring out how to send Elisp lists to my Rust functions. Something like this doesn't seem to compile:

#[emacs::defun]
fn mean(items: Vec<f64>) -> emacs::Result<f64> { ... }

as it complains that Vec is missing a FromLisp instance. I see that Elisp Vectors are supported, but lists aren't the same. Am I missing something really basic?

Please and thanks.

Replace `failure` with `thiserror`

Most improvements from failure are now incorporated into std::error::Error.

  • Convenient definition of structured errors is now covered by thiserror. This should be used to defined core error types.
  • Quick-and-easy error handling is now covered by anyhow. This is what modules should use.

This is also the chance to drop the Send + Sync requirement on core error types, and therefore the clunky TempValue type.

See also:

Use selected region as input to function

For instance, in this example

    // Define a function callable by Lisp code.
    #[defun]
    fn say_hello(env: &Env, name: String) -> Result<Value<'_>> {
        env.message(&format!("Hello, {}!", name))
    }

I'd like to be able to run this code in Emacs with a highlighted region used as the value of name. Is this possible?

Concurrency

I am playing around with exposing some of Rust's rayon crate to Emacs. I've started with attempting to implement join:

#[emacs::defun]
fn join<'a>(env: &Env, fa: Value<'a>, fb: Value<'a>) -> emacs::Result<()> {
    env.message("racing: Entered join.")?;

    let la = Lambda::new(fa);
    let lb = Lambda::new(fb);
    let a = || la.call();
    let b = || lb.call();

    env.message("racing: Invoking rayon...")?;

    let (ra, rb) = rayon::join(a, b);

    env.message(format!("ra: {}", ra.is_ok()))?;
    env.message(format!("rb: {}", rb.is_ok()))?;

    Ok(())
}

Ignoring the return type for the moment. After building and loading, I invoke it like this:

(racing-join (lambda () (message "Call from first lambda within Elisp!"))
             (lambda () (message "Call from second lambda within Elisp!")))

Here, Lambda is a wrapper type I've introduced to allow these evil trait instances:

unsafe impl<'a> Send for Lambda<'a> {}
unsafe impl<'a> Sync for Lambda<'a> {}

Otherwise the compiler complains of raw pointers (within Env) being unSendable.

My join function "works" only if I replace b with something that doesn't call lb, the second lambda. Otherwise Emacs complete freezes as soon as I invoke the Lisp shown above. Poking around in the source code of your library, I suspect it has something to do with Env. Having these unsafe trait instances as I do might just be impossible.

Do you have any ideas as to why Emacs would entirely freeze (as opposed to just erroring) when I invoke racing-join? Is Env entirely thread-unsafe?

Thank you kindly.

Cargo's subcommand `emacs-module`

Writing a module still involves many ad-hoc scripts (test.sh, load.sh) and manual steps (e.g. renaming files).

There should be a cargo's subcommand that supports at least the following:

  • new: Create a new module.
  • test: Run integration (ert) tests.
  • load: Load the module into a running Emacs daemon. Reload if it's already loaded.
  • package: Create a correctly-named file that can be dropped into a directory in load-path.

mod_in_name is confusing

mod_in_name doesn't seem to have any effect, neither as parameter to #[module] nor [defun], unless I'm misunderstanding its purpose.

E.g. a rust function

#[emacs::defun(mod_in_name = false)]
fn foo(_env: &emacs::Env, n: i64) -> emacs::Result<i64> {
   Ok(n)
}

is defined in elisp as module-name-foo instead of just foo.

Notice that this is also true for the test cases of this project. See e.g. vec_size in test-module/src/test_vector.rs, which is called from elisp as t/vec-size

[Feature Request] Consider impl IntoLispArgs for AsRef<[T]> where T: IntoLisp

Some time I found it's usual to convert a Vec of type implemented IntoLisp (e.g. Vec<String> ) trait to a Lisp list.

But env.list just accept a type implemented IntoLispArgs , so only AsRef<[Value]> or tuple of type implemented IntoLisp can be used.

I have to convert a Vec<String> to Vec<Value> and map can't be used here since into_lisp return a Result<Value>.

Can you consider impl IntoLispArgs for AsRef<[T]> where T: IntoLisp?

`IntoLisp` for `(A, B)`

I should probably get off my butt and try implementing some of these myself eh? Haha. Anyway, this seems like another logical instance to have. Off the top of my head, it should be rendered into a Lisp cons-cell (i.e. (a . b)).

Failed to require the module

I followed the user guide and when try to (require 'greeting), the following message showed

ad-Advice-require: Loading file /home/hekinami/.emacs.d/elpa/helm-20180222.2124/helm-command.elc failed to provide feature ‘greeting’

And failed to require.

I tried to (load "greeting"), it returned t, but I cannot use the feature written in the modlue.

Great Project, thank you!

I just ran through the hello, Emacs! tutorial and I have to say, I am blown away by how easy that was. Thanks so much for making what I was sure was going to be a hellish experience so effortless.

How to embed 2 types in user-ptr, when one of them is lifetime-constrained by the other?

I'm trying to convert a rust library to be able to run in Emacs but I've run into an issue when trying to upgrade from 0.9.0 to 0.10.0+. I get an error about rust being able to infer appropriate lifetimes for a struct. This code compiles perfectly fine in 0.9.0, but once you added the static lifetimes requirement to user_ptrin0.10.0`, Rust has refused to compile. Unfortunately, I haven't been able to figure out a work around and I was wondering if you had any suggestions for how I could resolve or work around this issue.

If you would like to see where this is happening in my code, you can find it here. But I've created a minimal program that recreates the same error message. Which can be found below:

I think the issue is because I've got a struct that has an explicit lifetime 'a, and it's getting this lifetime from another user_ptr being passed into the function and rust is getting confused about how to ensure that the struct with lifetime 'a has a static lifetime.

#[macro_use]
extern crate emacs;

use emacs::{Result};
use std::borrow::Cow;
struct Foo{
  string: String
}

struct Bar <'a>{
  sub_str: Cow<'a, str>,
}

#[defun(user_ptr)]
fn run_function(foo: &Foo)-> Result<Bar>{
  Ok(Bar{
    sub_str: Cow::from(foo.string),
  })
}

error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/main.rs:15:17
|
15 | fn run_function(foo: &Foo)-> Result{
| ^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the function body at 14:1...
--> src/main.rs:14:1
|
14 | #[defun(user_ptr)]
| ^^^^^^^^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:15:17
|
15 | fn run_function(foo: &Foo)-> Result{
| ^^^
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type Bar<'_> will meet its required lifetime bounds
--> src/main.rs:15:30
|
15 | fn run_function(foo: &Foo)-> Result{

Why bring emacs-module.h in version control ?

Hello,

Thanks for this project, I wanted to try a first FFI project so I wrote small bindings, and I was wondering how a more fleshed out implementation would look with macros and all so that's nice.

I'm currently wondering why you brought in source the emacs-module.h header ( here ) and only took the 25 version of it. It seems that it prevents users from using Emacs 26+ API.

The "naive" way I used was to use bindgen with a simple wrapper.h that is only

#include <emacs-module.h>

This way the build step automatically fetches and updates bindings for the currently included emacs header, and the compilation of the module will fail if the code uses an API that is absent on their system (emacs_env gets aliased to the most recent emacs_env type). What are the inconvenients of using such a method ?

Enable conversion for Vec<u8>

A "String" in Elisp VM can be used to present a byte slice Vec<u8>, not only a regular string. We can enable this conversion for the convenience. And we can deprecate utf-8-validation flag because user should use Vec<u8> to access a byte-slice and a string should always be valid utf-8.

Permissive `FromLisp` for numeric types?

Thanks again for the cool library. General question: should into_rust::<f64>() succeed for non-float literals like 1? Currently it fails, but I'm not sure what users should expect in general here.

Thoughts? Thanks you kindly.

Missing crate attribute `#[feature(maybe_uninit)`

cargo build
    Updating `git://mirrors.ustc.edu.cn/crates.io-index` index
    Blocking waiting for file lock on package cache lock
    Blocking waiting for file lock on package cache lock
   Compiling emacs v0.10.1
error[E0658]: use of unstable library feature 'maybe_uninit'
 --> /home/chino/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/emacs-0.10.1/src/error.rs:4:5
  |
4 | use std::mem::MaybeUninit;
  |     ^^^^^^^^^^^^^^^^^^^^^
  |
  = note: for more information, see https://github.com/rust-lang/rust/issues/53491
  = help: add #![feature(maybe_uninit)] to the crate attributes to enable

error[E0658]: use of unstable library feature 'maybe_uninit'
   --> /home/chino/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/emacs-0.10.1/src/error.rs:111:26
    |
111 |         let mut symbol = MaybeUninit::uninit();
    |                          ^^^^^^^^^^^^^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/53491
    = help: add #![feature(maybe_uninit)] to the crate attributes to enable

error[E0658]: use of unstable library feature 'maybe_uninit'
   --> /home/chino/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/emacs-0.10.1/src/error.rs:112:24
    |
112 |         let mut data = MaybeUninit::uninit();
    |                        ^^^^^^^^^^^^^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/53491
    = help: add #![feature(maybe_uninit)] to the crate attributes to enable

error[E0658]: use of unstable library feature 'maybe_uninit'
   --> /home/chino/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/emacs-0.10.1/src/error.rs:213:22
    |
213 |         symbol: &mut MaybeUninit<emacs_value>,
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/53491
    = help: add #![feature(maybe_uninit)] to the crate attributes to enable

error[E0658]: use of unstable library feature 'maybe_uninit'
   --> /home/chino/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/emacs-0.10.1/src/error.rs:214:20
    |
214 |         data: &mut MaybeUninit<emacs_value>,
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/53491
    = help: add #![feature(maybe_uninit)] to the crate attributes to enable

error[E0658]: use of unstable library feature 'maybe_uninit'
   --> /home/chino/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/emacs-0.10.1/src/error.rs:120:60
    |
120 |                     symbol: unsafe { TempValue::new(symbol.assume_init()) },
    |                                                            ^^^^^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/53491
    = help: add #![feature(maybe_uninit)] to the crate attributes to enable

error[E0658]: use of unstable library feature 'maybe_uninit'
   --> /home/chino/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/emacs-0.10.1/src/error.rs:121:56
    |
121 |                     data: unsafe { TempValue::new(data.assume_init()) },
    |                                                        ^^^^^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/53491
    = help: add #![feature(maybe_uninit)] to the crate attributes to enable

error[E0658]: use of unstable library feature 'maybe_uninit'
   --> /home/chino/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/emacs-0.10.1/src/error.rs:128:54
    |
128 |                     tag: unsafe { TempValue::new(tag.assume_init()) },
    |                                                      ^^^^^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/53491
    = help: add #![feature(maybe_uninit)] to the crate attributes to enable

error[E0658]: use of unstable library feature 'maybe_uninit'
   --> /home/chino/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/emacs-0.10.1/src/error.rs:129:58
    |
129 |                     value: unsafe { TempValue::new(value.assume_init()) },
    |                                                          ^^^^^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/53491
    = help: add #![feature(maybe_uninit)] to the crate attributes to enable

error[E0658]: use of unstable library feature 'maybe_uninit'
   --> /home/chino/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/emacs-0.10.1/src/error.rs:216:60
    |
216 |         raw_call_no_exit!(self, non_local_exit_get, symbol.as_mut_ptr(), data.as_mut_ptr())
    |                                                            ^^^^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/53491
    = help: add #![feature(maybe_uninit)] to the crate attributes to enable

error[E0658]: use of unstable library feature 'maybe_uninit'
   --> /home/chino/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/emacs-0.10.1/src/error.rs:216:79
    |
216 |         raw_call_no_exit!(self, non_local_exit_get, symbol.as_mut_ptr(), data.as_mut_ptr())
    |                                                                               ^^^^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/53491
    = help: add #![feature(maybe_uninit)] to the crate attributes to enable

error: aborting due to 11 previous errors

Support long-lived values that are not bound to &Env (GlobalValue)

  • Module code can store values for later use, e.g. in background threads.
  • Frequently-used symbols won't require repeated intern calls into the Lisp runtime. We can have emacs::sym::nil, emacs::sym::t. Modules will also be able to declare symbols they often use.
  • Error handling will not need unsafe (even though the safety requirement is almost trivial currently).

The biggest problem with this is that free_global_ref() requires an emacs_env, thus cannot be used directly in GlobalValue::drop() (this is likely a mis-design in emacs-module (BEAM's enif_release_resource doesn't need an env, for example)). There are 2 potential ways to solve this:

  • Add fn free(self, env: &Env), and just leak on normal drops. They are supposed to be long-lived anyway.
  • Add a "mini-GC" by globally tracking to-be-free values, and freeing them in Env::drop(), once in a while.

[crash] Invalid objects returned from my module function

Hi,

I'm using emacs-module-rs in some of my projects. I just made a small module that convert a json string to a lisp object.
You can see the code here, it's very small.

When a big json object is returned, it makes emacs crash. It doesn't happen with small objects.
It seems that the lisp object is not valid:

Stack traces


0  in terminate_due_to_signal of ../../src/emacs.c:369
1  in die of ../../src/alloc.c:7434
2  in XSTRING of ../../src/lisp.h:1395
3  in SDATA of ../../src/lisp.h:1446
4  in print_object of ../../src/print.c:1930
5  in print_vectorlike of ../../src/print.c:1713
6  in print_object of ../../src/print.c:2104
7  in print of ../../src/print.c:1150
8  in Fprin1 of ../../src/print.c:648
9  in print_error_message of ../../src/print.c:964
10 in Fcommand_error_default_function of ../../src/keyboard.c:1049
11 in funcall_subr of ../../src/eval.c:2901
12 in Ffuncall of ../../src/eval.c:2821
13 in call3 of ../../src/eval.c:2688
14 in cmd_error_internal of ../../src/keyboard.c:1004
15 in read_process_output_error_handler of ../../src/process.c:5803
16 in internal_condition_case_1 of ../../src/eval.c:1352
17 in read_and_dispose_of_process_output of ../../src/process.c:6008
18 in read_process_output of ../../src/process.c:5919
19 in wait_reading_process_output of ../../src/process.c:5616
20 in kbd_buffer_get_event of ../../src/keyboard.c:3822
21 in read_event_from_main_queue of ../../src/keyboard.c:2157
22 in read_decoded_event_from_main_queue of ../../src/keyboard.c:2221
23 in read_char of ../../src/keyboard.c:2808
24 in read_filtered_event of ../../src/lread.c:674
25 in Fread_event of ../../src/lread.c:786
26 in funcall_subr of ../../src/eval.c:2901
27 in Ffuncall of ../../src/eval.c:2821
28 in exec_byte_code of ../../src/bytecode.c:632
29 in funcall_lambda of ../../src/eval.c:3022
30 in Ffuncall of ../../src/eval.c:2823
31 in exec_byte_code of ../../src/bytecode.c:632
32 in funcall_lambda of ../../src/eval.c:3022
33 in Ffuncall of ../../src/eval.c:2823
34 in exec_byte_code of ../../src/bytecode.c:632
35 in funcall_lambda of ../../src/eval.c:3022
36 in Ffuncall of ../../src/eval.c:2823
37 in exec_byte_code of ../../src/bytecode.c:632
38 in funcall_lambda of ../../src/eval.c:3022
39 in Ffuncall of ../../src/eval.c:2823
40 in exec_byte_code of ../../src/bytecode.c:632
41 in funcall_lambda of ../../src/eval.c:3022
42 in Ffuncall of ../../src/eval.c:2823
43 in exec_byte_code of ../../src/bytecode.c:632
44 in funcall_lambda of ../../src/eval.c:3022
45 in Ffuncall of ../../src/eval.c:2823
46 in exec_byte_code of ../../src/bytecode.c:632
47 in funcall_lambda of ../../src/eval.c:3022
48 in Ffuncall of ../../src/eval.c:2823
49 in Fapply of ../../src/eval.c:2441
50 in funcall_subr of ../../src/eval.c:2876
51 in Ffuncall of ../../src/eval.c:2821
52 in exec_byte_code of ../../src/bytecode.c:632
53 in funcall_lambda of ../../src/eval.c:3022
54 in Ffuncall of ../../src/eval.c:2823
55 in call1 of ../../src/eval.c:2672
56 in timer_check_2 of ../../src/keyboard.c:4333
57 in timer_check of ../../src/keyboard.c:4395
58 in readable_events of ../../src/keyboard.c:3352
59 in get_input_pending of ../../src/keyboard.c:6808
60 in swallow_events of ../../src/keyboard.c:4135
61 in sit_for of ../../src/dispnew.c:5783
62 in read_char of ../../src/keyboard.c:2723
63 in read_key_sequence of ../../src/keyboard.c:9150
64 in command_loop_1 of ../../src/keyboard.c:1370
65 in internal_condition_case of ../../src/eval.c:1332
66 in command_loop_2 of ../../src/keyboard.c:1111
67 in internal_catch of ../../src/eval.c:1097
68 in command_loop of ../../src/keyboard.c:1090
69 in recursive_edit_1 of ../../src/keyboard.c:696
70 in Frecursive_edit of ../../src/keyboard.c:767
71 in main of ../../src/emacs.c:1720

0  in terminate_due_to_signal of ../../src/emacs.c:369
1  in emacs_abort of ../../src/sysdep.c:2426
2  in print_vectorlike of ../../src/print.c:1759
3  in print_object of ../../src/print.c:2104
4  in print of ../../src/print.c:1150
5  in Fprin1 of ../../src/print.c:648
6  in print_error_message of ../../src/print.c:964
7  in Fcommand_error_default_function of ../../src/keyboard.c:1049
8  in funcall_subr of ../../src/eval.c:2901
9  in Ffuncall of ../../src/eval.c:2821
10 in call3 of ../../src/eval.c:2688
11 in cmd_error_internal of ../../src/keyboard.c:1004
12 in read_process_output_error_handler of ../../src/process.c:5803
13 in internal_condition_case_1 of ../../src/eval.c:1352
14 in read_and_dispose_of_process_output of ../../src/process.c:6008
15 in read_process_output of ../../src/process.c:5919
16 in wait_reading_process_output of ../../src/process.c:5616
17 in sit_for of ../../src/dispnew.c:5824
18 in read_char of ../../src/keyboard.c:2723
19 in read_key_sequence of ../../src/keyboard.c:9150
20 in command_loop_1 of ../../src/keyboard.c:1370
21 in internal_condition_case of ../../src/eval.c:1332
22 in command_loop_2 of ../../src/keyboard.c:1111
23 in internal_catch of ../../src/eval.c:1097
24 in command_loop of ../../src/keyboard.c:1090
25 in recursive_edit_1 of ../../src/keyboard.c:696
26 in Frecursive_edit of ../../src/keyboard.c:767
27 in main of ../../src/emacs.c:1720


Am I doing something wrong in my code ?
Is it the conversion from rust to emacs that fails somewhere ?
Or do you think it's a bug in emacs ?

Note that git-tube also makes crash my emacs when the buffer contains lots of diffs

Allow returning result directly?

Consider the following code(it does not compile).

#[defun]
fn demo_func(env: &Env) {
    let mut vec : Vec<Value<'_>> = Vec::with_capacity(1);
    let xx =  "xx".into_lisp(env).unwrap();
    vec.push(xx);
    return env.call("list", &vec);
}

I am a bit new to rust, but don't we need the following:
(or changing the defun to handle that case).

impl <'e> IntoLisp<'e> for Result<Value<'e>>
{
    fn into_lisp(self, env: &Env) -> Result<Value<'e>> {
        return self;
    }
}

Better way to call Lisp functions

Currently Lisp functions are called using Env::call. This has 2 drawbacks:

  • Arguments and return value must be of type Value. This requires a lot of .into_lisp(env)? and .into_rust() boilerplate.
  • Heap allocation is needed to hold the raw emacs_value arguments, while most of the time the number of arguments is statically known.

These can be solved by a macro. A basic version already exists as an internal macro: call_lisp!.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.