DEFUN ("kqueue-valid-p", Fkqueue_valid_p, Skqueue_valid_p, 1, 1, 0,
doc: /* Check a watch specified by its WATCH-DESCRIPTOR.
WATCH-DESCRIPTOR should be an object returned by `kqueue-add-watch'.
A watch can become invalid if the file or directory it watches is
deleted, or if the watcher thread exits abnormally for any other
reason. Removing the watch by calling `kqueue-rm-watch' also makes it
invalid. */)
(Lisp_Object watch_descriptor)
{
return NILP (assq_no_quit (watch_descriptor, watch_list)) ? Qnil : Qt;
}
How can I start this? From what I can tell, this function uses the global variable watch_list and I'm not sure how I can port this function while still referring to that variable.
@rirze it's not just a global variable, this is a static "global" c variable, which means Rust has no access to it, since it's only visible in that c file.
AFAIU, the only way there is is to rewrite all functions that refer to this variable at once.
Or remove the static var from the header, and manipulate it via getter/setter from C (expose getter/setter to C from Rust)
@denis631 Thank you for the detailed explanation! I will spend some time and figure out if I am able to translate all the code in this file to Rust then.
@rirze I guess the other option is to remove the static keyword from the variable in order to make it accessible from Rust.
IDK what's the right approach. I picked another function (low-hanging-fruit) which also accesses the global static variable. I did the getter/setter approach. https://github.com/remacs/remacs/pull/1550
Hope to hear from guys soon
get/set functions are not a bad solution here. This makes the access and update of the variable more obvious.
Making the variable truly global is also viable, but long term we would want to move back to a more managed piece of data. As a static variable, the C compiler ensures that the variable is initialized to zero "for free". Having Rust manage the variable means we need to ensure the same thing happens. A lazy static is an approach as well.
If this were not a port and we were writing Emacs from scratch today what would be the idiomatic thing? I suspect that would be to define a type and some methods/functions that interact with that type. Then somewhere in Emacs initialization an instance of that type would be made and stored. Code needing it would then make some form of access request like WatchDescriptor::get_current. This would likely be the right thing to do in Remacs as well. But yes, that is more work.
At some point we will need to step back and design proper Rust components.
Most helpful comment
get/set functions are not a bad solution here. This makes the access and update of the variable more obvious.
Making the variable truly global is also viable, but long term we would want to move back to a more managed piece of data. As a static variable, the C compiler ensures that the variable is initialized to zero "for free". Having Rust manage the variable means we need to ensure the same thing happens. A lazy static is an approach as well.
If this were not a port and we were writing Emacs from scratch today what would be the idiomatic thing? I suspect that would be to define a type and some methods/functions that interact with that type. Then somewhere in Emacs initialization an instance of that type would be made and stored. Code needing it would then make some form of access request like
WatchDescriptor::get_current. This would likely be the right thing to do in Remacs as well. But yes, that is more work.At some point we will need to step back and design proper Rust components.