Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

libsyntax: Remove extern mod foo { ... } from the language. #6375

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 40 additions & 41 deletions doc/rust.md
Original file line number Diff line number Diff line change
@@ -618,7 +618,7 @@ each of which may have some number of [attributes](#attributes) attached to it.

~~~~~~~~ {.ebnf .gram}
item : mod_item | fn_item | type_item | struct_item | enum_item
| static_item | trait_item | impl_item | foreign_mod_item ;
| static_item | trait_item | impl_item | extern_block ;
~~~~~~~~

An _item_ is a component of a crate; some module items can be defined in crate
@@ -752,10 +752,11 @@ link_attr : ident '=' literal ;
~~~~~~~~

An _`extern mod` declaration_ specifies a dependency on an external crate.
The external crate is then bound into the declaring scope as the `ident` provided in the `extern_mod_decl`.
The external crate is then bound into the declaring scope
as the `ident` provided in the `extern_mod_decl`.

The external crate is resolved to a specific `soname` at compile time, and a
runtime linkage requirement to that `soname` is passed to the linker for
The external crate is resolved to a specific `soname` at compile time,
and a runtime linkage requirement to that `soname` is passed to the linker for
loading at runtime. The `soname` is resolved at compile time by scanning the
compiler's library path and matching the `link_attrs` provided in the
`use_decl` against any `#link` attributes that were declared on the external
@@ -992,10 +993,10 @@ Thus the return type on `f` only needs to reflect the `if` branch of the conditi
#### Extern functions

Extern functions are part of Rust's foreign function interface,
providing the opposite functionality to [foreign modules](#foreign-modules).
Whereas foreign modules allow Rust code to call foreign code,
extern functions with bodies defined in Rust code _can be called by foreign code_.
They are defined in the same way as any other Rust function,
providing the opposite functionality to [external blocks](#external-blocks).
Whereas external blocks allow Rust code to call foreign code,
extern functions with bodies defined in Rust code _can be called by foreign
code_. They are defined in the same way as any other Rust function,
except that they have the `extern` modifier.

~~~
@@ -1011,7 +1012,8 @@ let fptr: *u8 = new_vec;
~~~

The primary motivation for extern functions is
to create callbacks for foreign functions that expect to receive function pointers.
to create callbacks for foreign functions that expect to receive function
pointers.

### Type definitions

@@ -1308,64 +1310,61 @@ impl Seq<bool> for u32 {
}
~~~~

### Foreign modules
### External blocks

~~~ {.ebnf .gram}
foreign_mod_item : "extern mod" ident '{' foreign_mod '} ;
foreign_mod : [ foreign_fn ] * ;
extern_block_item : "extern" '{' extern_block '} ;
extern_block : [ foreign_fn ] * ;
~~~

Foreign modules form the basis for Rust's foreign function interface. A
foreign module describes functions in external, non-Rust
libraries.
Functions within foreign modules are declared in the same way as other Rust functions,
with the exception that they may not have a body and are instead terminated by a semicolon.
External blocks form the basis for Rust's foreign function interface.
Declarations in an external block describe symbols
in external, non-Rust libraries.

Functions within external blocks
are declared in the same way as other Rust functions,
with the exception that they may not have a body
and are instead terminated by a semicolon.

~~~
# use core::libc::{c_char, FILE};
# #[nolink]

extern mod c {
extern {
fn fopen(filename: *c_char, mode: *c_char) -> *FILE;
}
~~~

Functions within foreign modules may be called by Rust code, just like functions defined in Rust.
The Rust compiler automatically translates between the Rust ABI and the foreign ABI.

The name of the foreign module has special meaning to the Rust compiler in
that it will treat the module name as the name of a library to link to,
performing the linking as appropriate for the target platform. The name
given for the foreign module will be transformed in a platform-specific way
to determine the name of the library. For example, on Linux the name of the
foreign module is prefixed with 'lib' and suffixed with '.so', so the
foreign mod 'rustrt' would be linked to a library named 'librustrt.so'.
Functions within external blocks may be called by Rust code,
just like functions defined in Rust.
The Rust compiler automatically translates
between the Rust ABI and the foreign ABI.

A number of [attributes](#attributes) control the behavior of foreign
modules.
A number of [attributes](#attributes) control the behavior of external
blocks.

By default foreign modules assume that the library they are calling use the
standard C "cdecl" ABI. Other ABIs may be specified using the `abi`
attribute as in
By default external blocks assume
that the library they are calling uses the standard C "cdecl" ABI.
Other ABIs may be specified using the `abi` attribute as in

~~~{.xfail-test}
// Interface to the Windows API
#[abi = "stdcall"]
extern mod kernel32 { }
extern { }
~~~

The `link_name` attribute allows the default library naming behavior to
be overridden by explicitly specifying the name of the library.
The `link_name` attribute allows the name of the library to be specified.

~~~{.xfail-test}
#[link_name = "crypto"]
extern mod mycrypto { }
extern { }
~~~

The `nolink` attribute tells the Rust compiler not to do any linking for the foreign module.
This is particularly useful for creating foreign
modules for libc, which tends to not follow standard library naming
conventions and is linked to all Rust programs anyway.
The `nolink` attribute tells the Rust compiler
not to do any linking for the external block.
This is particularly useful for creating external blocks for libc,
which tends to not follow standard library naming conventions
and is linked to all Rust programs anyway.

## Attributes

3 changes: 2 additions & 1 deletion doc/tutorial-ffi.md
Original file line number Diff line number Diff line change
@@ -235,7 +235,8 @@ convention to use:
~~~~
#[cfg(target_os = "win32")]
#[abi = "stdcall"]
extern mod kernel32 {
#[link_name = "kernel32"]
extern {
fn SetEnvironmentVariableA(n: *u8, v: *u8) -> int;
}
~~~~
23 changes: 9 additions & 14 deletions src/libcore/os.rs
Original file line number Diff line number Diff line change
@@ -197,10 +197,10 @@ pub fn env() -> ~[(~str,~str)] {
}
#[cfg(unix)]
unsafe fn get_env_pairs() -> ~[~str] {
extern mod rustrt {
extern {
unsafe fn rust_env_pairs() -> **libc::c_char;
}
let environ = rustrt::rust_env_pairs();
let environ = rust_env_pairs();
if (environ as uint == 0) {
fail!(fmt!("os::env() failure getting env string from OS: %s",
os::last_os_error()));
@@ -677,9 +677,8 @@ pub fn list_dir(p: &Path) -> ~[~str] {
unsafe fn get_list(p: &Path) -> ~[~str] {
use libc::{dirent_t};
use libc::{opendir, readdir, closedir};
extern mod rustrt {
unsafe fn rust_list_dir_val(ptr: *dirent_t)
-> *libc::c_char;
extern {
unsafe fn rust_list_dir_val(ptr: *dirent_t) -> *libc::c_char;
}
let input = p.to_str();
let mut strings = ~[];
@@ -690,10 +689,8 @@ pub fn list_dir(p: &Path) -> ~[~str] {
debug!("os::list_dir -- opendir() SUCCESS");
let mut entry_ptr = readdir(dir_ptr);
while (entry_ptr as uint != 0) {
strings.push(
str::raw::from_c_str(
rustrt::rust_list_dir_val(
entry_ptr)));
strings.push(str::raw::from_c_str(rust_list_dir_val(
entry_ptr)));
entry_ptr = readdir(dir_ptr);
}
closedir(dir_ptr);
@@ -721,25 +718,23 @@ pub fn list_dir(p: &Path) -> ~[~str] {
};
use unstable::exchange_alloc::{malloc_raw, free_raw};
#[nolink]
extern mod rustrt {
extern {
unsafe fn rust_list_dir_wfd_size() -> libc::size_t;
unsafe fn rust_list_dir_wfd_fp_buf(wfd: *libc::c_void)
-> *u16;
}
fn star(p: &Path) -> Path { p.push("*") }
do as_utf16_p(star(p).to_str()) |path_ptr| {
let mut strings = ~[];
let wfd_ptr = malloc_raw(
rustrt::rust_list_dir_wfd_size() as uint);
let wfd_ptr = malloc_raw(rust_list_dir_wfd_size() as uint);
let find_handle =
FindFirstFileW(
path_ptr,
::cast::transmute(wfd_ptr));
if find_handle as int != INVALID_HANDLE_VALUE {
let mut more_files = 1 as libc::c_int;
while more_files != 0 {
let fp_buf = rustrt::rust_list_dir_wfd_fp_buf(
wfd_ptr);
let fp_buf = rust_list_dir_wfd_fp_buf(wfd_ptr);
if fp_buf as uint == 0 {
fail!(~"os::list_dir() failure:"+
~" got null ptr from wfd");
14 changes: 7 additions & 7 deletions src/libstd/priority_queue.rs
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@
use core::old_iter::BaseIter;

#[abi = "rust-intrinsic"]
extern "rust-intrinsic" mod rusti {
extern "rust-intrinsic" {
fn move_val_init<T>(dst: &mut T, src: T);
fn init<T>() -> T;
}
@@ -139,15 +139,15 @@ pub impl <T:Ord> PriorityQueue<T> {
while pos > start {
let parent = (pos - 1) >> 1;
if new > self.data[parent] {
let mut x = rusti::init();
let mut x = init();
x <-> self.data[parent];
rusti::move_val_init(&mut self.data[pos], x);
move_val_init(&mut self.data[pos], x);
pos = parent;
loop
}
break
}
rusti::move_val_init(&mut self.data[pos], new);
move_val_init(&mut self.data[pos], new);
}
}

@@ -162,14 +162,14 @@ pub impl <T:Ord> PriorityQueue<T> {
if right < end && !(self.data[child] > self.data[right]) {
child = right;
}
let mut x = rusti::init();
let mut x = init();
x <-> self.data[child];
rusti::move_val_init(&mut self.data[pos], x);
move_val_init(&mut self.data[pos], x);
pos = child;
child = 2 * pos + 1;
}

rusti::move_val_init(&mut self.data[pos], new);
move_val_init(&mut self.data[pos], new);
self.siftup(start, pos);
}
}
4 changes: 2 additions & 2 deletions src/libstd/rc.rs
Original file line number Diff line number Diff line change
@@ -95,7 +95,7 @@ mod test_rc {
}

#[abi = "rust-intrinsic"]
extern "rust-intrinsic" mod rusti {
extern "rust-intrinsic" {
fn init<T>() -> T;
}

@@ -159,7 +159,7 @@ impl<T: Owned> Drop for RcMut<T> {
unsafe {
(*self.ptr).count -= 1;
if (*self.ptr).count == 0 {
let mut x = rusti::init();
let mut x = init();
x <-> *self.ptr;
free(self.ptr as *c_void)
}
Loading