@@ -87,12 +87,14 @@ Check that these items exist on the computer:
8787- Tarantool 2.2
8888- A rustc compiler + cargo builder. Any modern version should work
8989
90- Create cargo project:
91- ``` shell script
90+ 1 . Create cargo project:
91+
92+ ``` console
9293$ cargo init --lib
9394```
9495
95- Add the following lines to ` Cargo.toml ` :
96+ 2 . Add the following lines to ` Cargo.toml ` :
97+
9698``` toml
9799[package ]
98100name = " easy"
@@ -101,37 +103,34 @@ edition = "2018"
101103# author, license, etc
102104
103105[dependencies ]
104- tarantool = " 0.4.2" # (1)
105- serde = " 1.0" # (2)
106+ tarantool = " 0.4.2"
107+ serde = " 1.0"
106108
107109[lib ]
108- crate-type = [" cdylib" ] # (3)
110+ crate-type = [" cdylib" ]
109111```
110112
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:
115114
116- Requests will be done using Tarantool as a client. Start Tarantool, and enter these requests:
117115``` 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 })
123122```
124123
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/ ) .
128128
129- #### Easy
129+ 4 . Edit ` lib.rs ` file and add the following lines:
130130
131- Edit ` lib.rs ` file and add the following lines:
132131``` rust
133132use std :: os :: raw :: c_int;
134- use tarantool_module :: tuple :: {FunctionArgs , FunctionCtx };
133+ use tarantool :: tuple :: {FunctionArgs , FunctionCtx };
135134
136135#[no_mangle]
137136pub extern " C" fn easy (_ : FunctionCtx , _ : FunctionArgs ) -> c_int {
@@ -144,55 +143,50 @@ pub extern "C" fn easy2(_: FunctionCtx, _: FunctionArgs) -> c_int {
144143 println! (" hello world -- easy2" );
145144 0
146145}
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+ }
147153```
148154
149- Compile the program:
150- ``` shell script
155+ #### Running a demo
156+
157+ Compile the program and start the server:
158+
159+ ``` console
151160$ cargo build
161+ $ LUA_CPATH=target/debug/lib? .so tarantool init.lua
152162```
153163
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:
157169
158- Now go back to the client and execute these requests:
159170``` 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' )
163173```
164174
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.
169177
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.
171180
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 .
174183
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}_ .
189187
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}_
192188``` 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' )
196190```
197191
198192... and this time the result will be ` hello world -- easy2 ` .
@@ -202,6 +196,7 @@ Conclusion: calling a Rust function is easy.
202196#### Harder
203197
204198Create a new crate "harder". Put these lines to ` lib.rs ` :
199+
205200``` rust
206201use serde :: {Deserialize , Serialize };
207202use std :: os :: raw :: c_int;
0 commit comments