@@ -87,12 +87,14 @@ Check that these items exist on the computer:
87
87
- Tarantool 2.2
88
88
- A rustc compiler + cargo builder. Any modern version should work
89
89
90
- Create cargo project:
91
- ``` shell script
90
+ 1 . Create cargo project:
91
+
92
+ ``` console
92
93
$ cargo init --lib
93
94
```
94
95
95
- Add the following lines to ` Cargo.toml ` :
96
+ 2 . Add the following lines to ` Cargo.toml ` :
97
+
96
98
``` toml
97
99
[package ]
98
100
name = " easy"
@@ -101,37 +103,34 @@ edition = "2018"
101
103
# author, license, etc
102
104
103
105
[dependencies ]
104
- tarantool = " 0.4.2" # (1)
105
- serde = " 1.0" # (2)
106
+ tarantool = " 0.4.2"
107
+ serde = " 1.0"
106
108
107
109
[lib ]
108
- crate-type = [" cdylib" ] # (3)
110
+ crate-type = [" cdylib" ]
109
111
```
110
112
111
- 1 . add to dependencies ` tarantool ` library;
112
- 1 . add to dependencies [ Serde] ( https://github.com/serde-rs/serde ) , this is optional and required if you want to use rust
113
- structures as a tuple values (see [ this example] ( #harder ) );
114
- 1 . you need to compile dynamic library.
113
+ 3 . Create the server entypoint named ` init.lua ` with the following script:
115
114
116
- Requests will be done using Tarantool as a client. Start Tarantool, and enter these requests:
117
115
``` lua
118
- box .cfg {listen = 3306 }
119
- box .schema .space .create (' capi_test' )
120
- box .space .capi_test :create_index (' primary' )
121
- net_box = require (' net.box' )
122
- capi_connection = net_box :new (3306 )
116
+ require (' easy' )
117
+ box .cfg ({listen = 3301 })
118
+ box .schema .func .create (' easy' , {language = ' C' , if_not_exists = true })
119
+ box .schema .func .create (' easy.easy2' , {language = ' C' , if_not_exists = true })
120
+ box .schema .user .grant (' guest' , ' execute' , ' function' , ' easy' , {if_not_exists = true })
121
+ box .schema .user .grant (' guest' , ' execute' , ' function' , ' easy.easy2' , {if_not_exists = true })
123
122
```
124
123
125
- In plain language: create a space named ` capi_test ` , and make a connection to self named ` capi_connection ` .
126
-
127
- Leave the client running. It will be used to enter more requests later.
124
+ If these commands appear unfamiliar, look at the Tarantool documentation:
125
+ - [ box.cfg()] ( https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_cfg/ ) ;
126
+ - [ box.schema.func.create()] ( https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_schema/func_create/ ) ;
127
+ - [ box.schema.user.grant()] ( https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_schema/user_grant/ ) .
128
128
129
- #### Easy
129
+ 4 . Edit ` lib.rs ` file and add the following lines:
130
130
131
- Edit ` lib.rs ` file and add the following lines:
132
131
``` rust
133
132
use std :: os :: raw :: c_int;
134
- use tarantool_module :: tuple :: {FunctionArgs , FunctionCtx };
133
+ use tarantool :: tuple :: {FunctionArgs , FunctionCtx };
135
134
136
135
#[no_mangle]
137
136
pub extern " C" fn easy (_ : FunctionCtx , _ : FunctionArgs ) -> c_int {
@@ -144,55 +143,50 @@ pub extern "C" fn easy2(_: FunctionCtx, _: FunctionArgs) -> c_int {
144
143
println! (" hello world -- easy2" );
145
144
0
146
145
}
146
+
147
+ #[no_mangle]
148
+ pub extern " C" fn luaopen_easy (_l : std :: ffi :: c_void ) -> c_int {
149
+ // Tarantool calls this function upon require("easy")
150
+ println! (" easy module loaded" );
151
+ 0
152
+ }
147
153
```
148
154
149
- Compile the program:
150
- ``` shell script
155
+ #### Running a demo
156
+
157
+ Compile the program and start the server:
158
+
159
+ ``` console
151
160
$ cargo build
161
+ $ LUA_CPATH=target/debug/lib? .so tarantool init.lua
152
162
```
153
163
154
- Start another shell. Change directory (` cd ` ) so that it is the same as the directory that the client is running in.
155
- Copy the compiled library (it is located in subfolder ` target/debug ` at you
156
- project sources folder) to the current folder and rename it to ` easy.so `
164
+ The [ LUA_CPATH] ( https://www.lua.org/pil/8.1.html ) is necessary because Rust layout conventions
165
+ slightly differs from those in Lua. Fortunately, Lua is rater flexible.
166
+
167
+ Now you're ready to make some requests. Open separate console window and run tarantool, we'll use it
168
+ as a client. In the tarantool console paste the following:
157
169
158
- Now go back to the client and execute these requests:
159
170
``` lua
160
- box .schema .func .create (' easy' , {language = ' C' })
161
- box .schema .user .grant (' guest' , ' execute' , ' function' , ' easy' )
162
- capi_connection :call (' easy' )
171
+ conn = require (' net.box' ).connect (3301 )
172
+ conn :call (' easy' )
163
173
```
164
174
165
- If these requests appear unfamiliar, read the descriptions of
166
- [ box.schema.func.create()] ( https://www.tarantool.io/en/doc/2.2/reference/reference_lua/box_schema/#box-schema-func-create ) ,
167
- [ box.schema.user.grant()] ( https://www.tarantool.io/en/doc/2.2/reference/reference_lua/box_schema/#box-schema-user-grant )
168
- and [ conn: call ()] ( https://www.tarantool.io/en/doc/2.2/reference/reference_lua/net_box/#net-box-call ) .
175
+ Again, check out [ net.box] ( https://www.tarantool.io/en/doc/latest/reference/reference_lua/net_box/ )
176
+ module documentation, if necessary.
169
177
170
- The function that matters is ` capi_connection:call('easy') ` .
178
+ The code above connects to the server and calls the 'easy' function. Since the ` easy() ` function in
179
+ ` lib.rs ` begins with ` println!("hello world") ` , the words "hello world" will appear in the server console.
171
180
172
- Its first job is to find the 'easy' function, which should be easy because by default Tarantool looks on the current directory
173
- for a file named ` easy.so ` .
181
+ Also, it checks that the call was successful. Since the ` easy() ` function in ` lib.rs ` ends
182
+ with return 0, there is no error message to display and the request is over .
174
183
175
- Its second job is to call the 'easy' function. Since the ` easy() ` function in ` lib.rs ` begins with ` println!("hello world") ` ,
176
- the words "hello world" will appear on the screen.
177
-
178
- Its third job is to check that the call was successful. Since the ` easy() ` function in ` lib.rs ` ends with return 0, there
179
- is no error message to display and the request is over.
180
-
181
- The result should look like this:
182
- ```
183
- tarantool> capi_connection:call('easy')
184
- hello world
185
- ---
186
- - []
187
- ...
188
- ```
184
+ Now let's call the other function in lib.rs - ` easy2() ` . This is almost the same as the ` easy() `
185
+ function, but there's a detail: when the file name is not the same as the function name, then we
186
+ have to specify _ {file-name}_ ._ {function-name}_ .
189
187
190
- Now let's call the other function in lib.rs - ` easy2() ` . This is almost the same as the ` easy() ` function, but there's a
191
- detail: when the file name is not the same as the function name, then we have to specify _ {file-name}_ ._ {function-name}_
192
188
``` lua
193
- box .schema .func .create (' easy.easy2' , {language = ' C' })
194
- box .schema .user .grant (' guest' , ' execute' , ' function' , ' easy.easy2' )
195
- capi_connection :call (' easy.easy2' )
189
+ conn :call (' easy.easy2' )
196
190
```
197
191
198
192
... and this time the result will be ` hello world -- easy2 ` .
@@ -202,6 +196,7 @@ Conclusion: calling a Rust function is easy.
202
196
#### Harder
203
197
204
198
Create a new crate "harder". Put these lines to ` lib.rs ` :
199
+
205
200
``` rust
206
201
use serde :: {Deserialize , Serialize };
207
202
use std :: os :: raw :: c_int;
0 commit comments