Skip to content

Commit 4ec03d1

Browse files
Add hello world example (#53)
1 parent d2b0418 commit 4ec03d1

File tree

3 files changed

+97
-0
lines changed

3 files changed

+97
-0
lines changed

guide/src/SUMMARY.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Summary
22

33
- [Introduction](./introduction.md)
4+
- [Examples](./examples/index.md)
5+
- [Hello World](./examples/hello_world.md)
46
- [Types](./types/index.md)
57
- [Primitive Numbers](./types/numbers.md)
68
- [`String`](./types/string.md)

guide/src/examples/hello_world.md

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# Hello World
2+
3+
Let's create a basic PHP extension. We will start by creating a new Rust library
4+
crate:
5+
6+
```sh
7+
$ cargo new hello_world --lib
8+
$ cd hello_world
9+
```
10+
11+
Let's set up our crate by adding `ext-php-rs` as a dependency and setting the
12+
crate type to `cdylib`. Update the `Cargo.toml` to look something like so:
13+
14+
### `Cargo.toml`
15+
16+
```toml
17+
[package]
18+
name = "hello_world"
19+
version = "0.1.0"
20+
edition = "2018"
21+
22+
[dependencies]
23+
ext-php-rs = "0.2"
24+
25+
[lib]
26+
crate-type = ["cdylib"]
27+
```
28+
29+
As the linker will not be able to find the PHP installation that we are
30+
dynamically linking to, we need to enable dynamic linking with undefined
31+
symbols. We do this by creating a Cargo config file in `.cargo/config.toml` with
32+
the following contents:
33+
34+
### `.cargo/config.toml`
35+
36+
```toml
37+
[build]
38+
rustflags = ["-C", "link-arg=-Wl,-undefined,dynamic_lookup"]
39+
```
40+
41+
Let's actually write the extension code now. We start by importing the
42+
`ext-php-rs` prelude, which contains most of the imports required to make a
43+
basic extension. We will then write our basic `hello_world` function, which will
44+
take a string argument for the callers name, and we will return another string.
45+
Finally, we write a `get_module` function which is used by PHP to find out about
46+
your module. The `#[php_module]` attribute automatically registers your new
47+
function so we don't need to do anything except return the `ModuleBuilder` that
48+
we were given.
49+
50+
### `src/lib.rs`
51+
52+
```rust
53+
# extern crate ext_php_rs;
54+
use ext_php_rs::prelude::*;
55+
56+
#[php_function]
57+
pub fn hello_world(name: String) -> String {
58+
format!("Hello, {}!", name)
59+
}
60+
61+
#[php_module]
62+
pub fn get_module(module: ModuleBuilder) -> ModuleBuilder {
63+
module
64+
}
65+
```
66+
67+
Let's make a test script.
68+
69+
### `test.php`
70+
71+
```php
72+
<?php
73+
74+
var_dump(hello_world("David"));
75+
```
76+
77+
Now let's build our extension and run our test script. This is done through
78+
`cargo` like any other Rust crate. It is required that the `php-config`
79+
executable is able to be found by the `ext-php-rs` build script.
80+
81+
The extension is stored inside `target/debug` (if you did a debug build,
82+
`target/release` for release builds). The file name will be based on your crate
83+
name, so for us it will be `libhello_world`. The extension is based on your OS -
84+
on Linux it will be `libhello_world.so` and on macOS it will be
85+
`libhello_world.dylib`.
86+
87+
```
88+
$ cargo build
89+
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
90+
$ php -dextension=./target/debug/libhello_world.dylib test.php
91+
string(13) "Hello, David!"
92+
```

guide/src/examples/index.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Examples
2+
3+
- [Hello World](./hello_world.md)

0 commit comments

Comments
 (0)