Does Rust have a dlopen equivalent - plugins

Does Rust have a way to make a program pluggable. In C the plugins I create are .so files that I load with dlopen. Does Rust provide a native way of doing the same thing?

The Rust FAQ officially endorses libloading. Beyond that, there are three different options I know of:
Use the shared_library crate
Use the dylib crate.
Use std::dynamic_lib, which is deprecated since Rust 1.5. (These docs are no longer available in version 1.32; it's likely the feature has been dropped altogether by now.)
I haven't tried any of these, so I cannot really say which is best or what the pros/cons are for the different variants. I'd strongly advise against using std::dynamic_lib at least, given that it's deprecated and will likely be made private at some point in the future.

Exactly,
And below is the complete use case example:
use std::unstable::dynamic_lib::DynamicLibrary;
use std::os;
fn load_cuda_library()
{
let path = Path::new("/usr/lib/libcuda.so");
// Make sure the path contains a / or the linker will search for it.
let path = os::make_absolute(&path);
let lib = match DynamicLibrary::open(Some(&path)) {
Ok(lib) => lib,
Err(error) => fail!("Could not load the library: {}", error)
};
// load cuinit symbol
let cuInit: extern fn(u32) -> u32 = unsafe {
match lib.symbol("cuInit") {
Err(error) => fail!("Could not load function cuInit: {}", error),
Ok(cuInit) => cuInit
}
};
let argument = 0;
let expected_result = 0;
let result = cuInit(argument);
if result != expected_result {
fail!("cuInit({:?}) != {:?} but equaled {:?}",
argument, expected_result, result)
}
}
fn main()
{
load_cuda_library();
}

Yes. There's a module std::unstable::dynamic_lib that enables dynamic loading of libraries. It's undocumented, though, as it's a highly experimental API (everything in std::unstable is undocumented). As #dbaupp suggests, the source is the best documentation (current version is af9368452).

Related

How to port following hook to reasonml

I have following custom hook
function useConstant(fn) {
const ref = React.useRef()
if (!ref.current) {
ref.current = fn()
}
return ref.current
}
and it seems quite hard to port this to reasonml, I have to use type cast twice, what's the ideal way?
external toAny: 'a => 'b = "%identity";
external toBool: 'a => bool = "%identity";
let useConstant = (fn: unit => 'a) => {
let ref: React.Ref.t('a) = toAny(React.useRef());
if (!toBool(React.Ref.current(ref))) {
React.Ref.setCurrent(ref, fn());
};
React.Ref.current(ref);
};
If I understand the purpose of the hook correctly, it's really just a reimplementation of React.useMemo. But for the sake of learning, here's an implementation that should work.
let useLazy = (fn: unit => 'a): 'a => {
let ref = React.useRef(None);
switch (React.Ref.current(ref)) {
| Some(value) => value
| None =>
let value = fn();
React.Ref.setCurrent(ref, Some(value));
value;
};
};
It uses the option type, which is specifically designed for cases like this. If there's no value, we represent that using options None value, and if there is a value we use Some. Instead of using if with JavaScript's semantically unclear concept of truthiness, we pattern match on the option using switch to find that it's None and the value needs to be computed, or Some to get at the value.
The use of option and pattern matching is really common in Reason code, so it's one you should really try to understand using the links provided above for more details if needed.
Note that you could also have used Lazy for this. But that's far less commonly used and therefore also much less useful to learn.

How to select symbols onWorkspaceSymbol

I am developing an extension for visual studio code using language server protocol, and I am including the support for "Go to symbol in workspace". My problem is that I don't know how to select the matches...
Actually I use this function I wrote:
function IsInside(word1, word2)
{
var ret = "";
var i1 = 0;
var lenMatch =0, maxLenMatch = 0, minLenMatch = word1.length;
for(var i2=0;i2<word2.length;i2++)
{
if(word1[i1]==word2[i2])
{
lenMatch++;
if(lenMatch>maxLenMatch) maxLenMatch = lenMatch;
ret+=word1[i1];
i1++;
if(i1==word1.length)
{
if(lenMatch<minLenMatch) minLenMatch = lenMatch;
// Trying to filter like VSCode does.
return maxLenMatch>=word1.length/2 && minLenMatch>=2? ret : undefined;
}
} else
{
ret+="Z";
if(lenMatch>0 && lenMatch<minLenMatch)
minLenMatch = lenMatch;
lenMatch=0;
}
}
return undefined;
}
That return the sortText if the word1 is inside the word2, undefined otherwise. My problem are cases like this:
My algorithm see that 'aller' is inside CallServer, but the interface does not mark it like expected.
There is a library or something that I must use for this? the code of VSCode is big and complex and I don't know where start looking for this information...
VSCode's API docs for provideWorkspaceSymbols() provide the following guidance (which I don't think your example violates):
The query-parameter should be interpreted in a relaxed way as the editor will apply its own highlighting and scoring on the results. A good rule of thumb is to match case-insensitive and to simply check that the characters of query appear in their order in a candidate symbol. Don't use prefix, substring, or similar strict matching.
These docs were added in response to this discussion, where somebody had very much the same issue as you.
Having a brief look at VSCode sources, internally it seems to use filters.matchFuzzy2() for the highlighting (see here and here). I don't think it's exposed in the API, so you would probably have to copy it if you wanted the behavior to match exactly.

How to get ID from file added to GridFS with the Rust MongoDB driver?

The mongodb 0.1.4 bindings for Rust provide a GridFS implementation.
As from the code and the examples there is a put, but it doesn't return an object ID.
My workaround is to put the file into GridFS and then open it again to retrieve the ID:
fn file_to_mongo(gridfs: &Store, fpath: &PathBuf) -> bson::oid::ObjectId {
gridfs.put(fpath.to_str().unwrap().to_owned());
let mut file = gridfs.open(fpath.to_str().unwrap().to_owned()).unwrap();
let id = file.doc.id.clone();
file.close().unwrap();
id
}
Is there a better way?
I don't have MongoDB running and I don't really know anything about it, but this at least has the right signature and compiles.
extern crate bson;
extern crate mongodb;
use mongodb::gridfs::{Store,ThreadedStore};
use mongodb::error::Result as MongoResult;
use std::{fs, io};
fn my_put(store: &Store, name: String) -> MongoResult<bson::oid::ObjectId> {
let mut f = try!(fs::File::open(&name));
let mut file = try!(store.create(name));
try!(io::copy(&mut f, &mut file));
try!(file.close());
Ok(file.doc.id.clone())
}
Recall that most Rust libraries are open-source and you can even browse the source directly from the documentation. This function is basically just a hacked version of the existing put.

Procedural macro parsing weirdness in Rust

I'm trying to parse a macro similar to this one:
annoying!({
hello({
// some stuff
});
})
Trying to do this with a procedural macro definition similar to the following, but I'm getting a behaviour I didn't expect and I'm not sure I'm doing something I'm not supposed to or I found a bug. In the following example, I'm trying to find the line where each block is,
for the first block (the one just inside annoying!) it reports the correct line, but for the inner block, when I try to print them it's always 1, no matter where the code is etc.
#![crate_type="dylib"]
#![feature(macro_rules, plugin_registrar)]
extern crate syntax;
extern crate rustc;
use macro_result::MacroResult;
use rustc::plugin::Registry;
use syntax::ext::base::{ExtCtxt, MacResult};
use syntax::ext::quote::rt::ToTokens;
use syntax::codemap::Span;
use syntax::ast;
use syntax::parse::tts_to_parser;
mod macro_result;
#[plugin_registrar]
pub fn plugin_registrar(registry: &mut Registry) {
registry.register_macro("annoying", macro_annoying);
}
pub fn macro_annoying(cx: &mut ExtCtxt, _: Span, tts: &[ast::TokenTree]) -> Box<MacResult> {
let mut parser = cx.new_parser_from_tts(tts);
let lo = cx.codemap().lookup_char_pos(parser.span.lo);
let hi = cx.codemap().lookup_char_pos(parser.span.hi);
println!("FIRST LO {}", lo.line); // real line for annoying! all cool
println!("FIRST HI {}", hi.line); // real line for annoying! all cool
let block_tokens = parser.parse_block().to_tokens(cx);
let mut block_parser = tts_to_parser(cx.parse_sess(), block_tokens, cx.cfg());
block_parser.bump(); // skip {
block_parser.parse_ident(); // hello
block_parser.bump(); // skip (
// block lines
let lo = cx.codemap().lookup_char_pos(block_parser.span.lo);
let hi = cx.codemap().lookup_char_pos(block_parser.span.hi);
println!("INNER LO {}", lo.line); // line 1? wtf?
println!("INNER HI {}", hi.line); // line 1? wtf?
MacroResult::new(vec![])
}
I think the problem might be the fact that I'm creating a second parser to parse the inner block, and that might be making the Span types inside it go crazy, but I'm not sure that's the problem or how to keep going from here. The reason I'm creating this second parser is so I can recursively parse what's inside each of the blocks, I might be doing something I'm not supposed to, in which case a better suggestion would be very welcome.
I believe this is #15962 (and #16472), to_tokens has a generally horrible implementation. Specifically, anything non-trivial uses ToSource, which just turns the code to a string, and then retokenises that (yes, it's not great at all!).
Until those issues are fixed, you should just handle the original tts directly as much as possible. You could approximate the right span using the .span of the parsed block (i.e. return value of parse_block), which will at least focus the user's attention on the right area.

Get package childs from a package

In Eclipse, how can I get the package's children?
Consider this example:
+ org.stack
org.stack.test
- StackTest.java
- Stack.java
When we do IPackageFragment.getChildren() in org.stack, the Eclipse JDT only returns the compilation unit (Java Files)! But I want all children of a package: all ICompilationUnits and all Packages.
In this example when I apply IPackageFragment.getChildren() in org.stack, I want the org.stack.test and the ICompilationUnit Stack.java...
How can I do this?
IPackageFragment is not the correct starting point. You have to ask a higher level for the packages:
IPackageFragment: A single package. It contains ICompilationUnits or IClassFiles, depending on whether the IPackageFragmentRoot is of type source or of type binary. Note that IPackageFragment are not organized as parent-children. E.g. net.sf.a is not the parent of net.sf.a.b. They are two independent children of the same IPackageFragmentRoot.
Have a look at this article about the AST
Here's some code that should be close to what you needed. (Since we're a bit past 2011, I doubt it will help you much, but maybe it will help somebody else.) Doubtless it can stand some improvement.
Since it doesn't seem possible to directly recurse downward from the IPackageFragment (as mentioned by Kai), the basic idea is to get the higher level IPackageFragmentRoot and filter it's children based on the original fragment's path.
PackageFragment originFragment; // = org.stack's fragment
try {
String fragmentPath = originFragment.getPath().toString();
IJavaElement parent = originFragment.getParent();
ArrayList<IJavaElement> allChildren =
new ArrayList<IJavaElement>();
if (parent instanceof IPackageFragmentRoot) {
IPackageFragmentRoot root = (IPackageFragmentRoot)parent;
IJavaElement[] rootChildren = root.getChildren();
// originsFragments includes the origin and all package
// fragments beneath it
List<IJavaElement> originsFragments =
Arrays.asList(rootChildren).stream()
.filter(c -> c.getPath().toString().startsWith(fragmentPath))
.collect(Collectors.toList());
allChildren.addAll(originsFragments);
// Gather the children of the package fragments
for (IJavaElement o : originsFragments) {
if (o instanceof IPackageFragment ) {
IPackageFragment oFragment = (IPackageFragment)o;
IJavaElement[] fChildren = oFragment.getChildren();
allChildren.addAll(Arrays.asList(fChildren));
}
}
}
} catch (JavaModelException e) {
e.printStackTrace();
}
An alternative inelegant solution would be to start with the original fragment's path and then use Java's file and directory facilities to descend through the directory hierarchy. Then, you can use IJavaProject's findPackageFragment(IPath path) to connect to the proper IPackageFragments.
you need to do it in a recursive way.
here's some pseudo code
findAllClasses(package, classesCollection) {
for(Class c: package.getClasses)
classesCollection.add(c.getResourcePath)
if(package.hasChildPackages)
for(Package p: packages)
findAllClasses(p, classesCollection)
}