|
最初に、プロジェクトを作成しよう。下記のコマンドを実行して下さい。
Windows では、powershell 環境で実行してください。cmd では、utf-8 テキストで扱うため日本語がうまく表示されません。
因みに、当方の Linux(CentOS 7) では、lib 不足でビルドできません。
cargo new --bin trigon_func_gui
cd trigon_func_gui
下記の構成で、ソースファイルおよび設定ファイルを編集します。
今回は、ファイルが大きいので、zip で、固めた全体trigon_func_gui.zip と trigon_func_gui_build.zip(ビルド済み) を提供させていただきます。自由にご利用願います。
|
+- assets
| |
| +- fonts
| |
| +- NotoSans
| |
| +- LICENSE-2.0.txt
| +- NotoSans-Bold.ttf
| +- NotoSans-BoldItalic.ttf
| +- NotoSans-Italic.ttf
| +- NotoSans-Regular.ttf
|
+- Cargo.toml
|
+- build.rs
|
+- src/
| |
| +- main.rs
| |
| +- c/
| |
| +- mysystem.c
|
+- color_chooser_py.py
|
|
Cargo.toml は、下記のように、fibonacci に、青色部を書き足します。
[package]
name = "trigon_func_gui"
version = "0.1.0"
authors = ["kamifuji"]
edition = "2018"
# [[bin]]
# name = "trigon_func_gui"
links = "mysystem"
build = "build.rs"
[dependencies.conrod]
version = "0.53.0"
features = ["glium", "winit"]
[dependencies]
find_folder = "*"
libc = "0.2.0"
[build-dependencies]
gcc = "0.3"
build.rs は、下記のように書きます。
extern crate gcc;
fn main(){
gcc::Config::new()
.file("src/c/mysystem.c")
.include("src")
.compile("libfoo.a");
}
src/main.rs の説明は、後程にして、src/c/mysystem.c は、下記のように書きます。
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>
double sin_deg( double th ) {
double rval, ath ;
ath = th * acos( -1.0 ) / 180.0 ;
rval = sin( ath );
// printf( "acos( -1.0 ) = %10.5f \n" ,acos(-1.0) );
// printf( "th = %10.5f ath = %10.5f rval = %10.5f \n", th, ath, rval );
return( rval );
}
double cos_deg( double th ) {
double rval, ath ;
ath = th * acos( -1.0 ) / 180.0 ;
rval = cos( ath );
return( rval );
}
double tan_deg( double th ) {
double rval, ath ;
ath = th * acos( -1.0 ) / 180.0 ;
rval = tan( ath );
return( rval );
}
double asin_deg( double th ) {
double rval, ath ;
ath = asin( th );
rval = ath * 180.0 / acos( -1.0 ) ;
return( rval );
}
double acos_deg( double th ) {
double rval, ath ;
ath = acos( th );
rval = ath * 180.0 / acos( -1.0 ) ;
return( rval );
}
double atan_deg( double th ) {
double rval, ath ;
ath = atan( th );
rval = ath * 180.0 / acos( -1.0 ) ;
return( rval );
}
double atan2_deg( double y, double x ) {
double rval, ath ;
ath = atan2( y, x );
rval = ath * 180.0 / acos( -1.0 ) ;
return( rval );
}
それでは、今回の改修された src/main.rs について、説明していきます。
C の関数の呼び出しよう extern 宣言を下記のように追加し書きます。( 1 から 30 行 )
#[link(name="mysystem", kind="static")]
extern{
fn sin_deg( input: f64) -> f64 ;
}
extern{
fn cos_deg( input: f64) -> f64 ;
}
extern{
fn tan_deg( input: f64) -> f64 ;
}
extern{
fn asin_deg( input: f64) -> f64 ;
}
extern{
fn acos_deg( input: f64) -> f64 ;
}
extern{
fn atan_deg( input: f64) -> f64 ;
}
extern{
fn atan2_deg( input: f64, input: f64 ) -> f64 ;
}
// 省略
次に、実行時のパラメータ( args )の解析部を説明します。( 65 から 79 行 )
use std::env;
// 省略
fn main() {
let args: Vec = env::args().collect();
let mut func = String::from("sin");
let mut spram = String::from("0.0");
let mut spram2 = String::from("1.0,0.0");
let argc = args.len() ;
if argc == 1 {
}
else if argc == 2 {
func = args[1].clone();
}
else if argc >= 3 {
func = args[1].clone();
spram = args[2].clone();
}
// 省略
1 番目の引数( args[1].clone() )で、 関数種別を func に、2 番目の引数( args[2].clone() )で、関数への引数を spram に、保存されます。args が不足したときは、適宜 func および spram は、"sin" および "0.0" が仮定されます。
次に、fn set_widgets() の改修部を説明します。( 188 から 250 行 )
// 省略
fn set_widgets(ref mut ui: conrod::UiCell, ids: &mut Ids, text: &mut String, answer: &mut String) {
widget::Canvas::new()
.pad(0.0)
.color(conrod::color::rgb(0.5, 0.9, 0.5))
.set(ids.canvas, ui);
let canvas_wh = ui.wh_of(ids.canvas).unwrap();
// title
widget::Text::new("Trigon_Func Calculuator")
.mid_top_with_margin_on(ids.canvas, 5.0)
.font_size(20)
.color(color::WHITE)
.set(ids.title, ui);
// Top sin_deg
// textbox
for event in widget::TextBox::new(text)
.font_size(15)
.w_h((canvas_wh[0] - 90.) / 2., 30.0)
.mid_left_with_margin_on(ids.canvas, 30.0)
.border(2.0)
.border_color(color::rgb(0.0, 0.8, 0.0))
.color(color::WHITE)
.set(ids.text_box, ui)
{
match event {
widget::text_box::Event::Enter => println!("TextBox {:?}", text),
widget::text_box::Event::Update(string) => *text = string,
}
}
// button
if widget::Button::new()
// .mid_bottom_with_margin_on(ids.canvas, 40.0)
.w_h((canvas_wh[0] - 90.) / 2., 30.0)
.right_from(ids.text_box, 30.0)
.rgb(0.9, 0.99, 0.9)
.border_color(color::rgb(0.0, 0.8, 0.0))
.border(2.0)
.label("sin_deg !")
.set(ids.button, ui)
.was_clicked()
{
if let Ok(num) = text.parse::<f64>() {
unsafe {
*answer = format!("{:.5}", sin_deg(num));
}
println!( "sin_deg( {:.5} ) = {}", num ,answer );
} else {
println!("invalid number");
}
}
// result
widget::Text::new(answer)
.mid_bottom_with_margin_on(ids.canvas, 10.0)
.font_size(20)
.color(color::WHITE)
.set(ids.result, ui);
// sin_deg Btm
}
// 省略
C 言語で書かれた関数を呼び出すコードは、unsafe { } 内に書いてください。( 裏本 19.1 節を、見てください。)
青色部を改修して、sin_deg 関数用をコーディングしました。同様に
fn set_widgets2() cos_deg 関数用に
fn set_widgets3() tan_deg 関数用に
fn set_widgets4() asin_deg 関数用に
fn set_widgets5() acos_deg 関数用に
fn set_widgets6() atan_deg 関数用に
fn set_widgets7() atan2_deg 関数用に
7 個の set_widgets を作成します。
次に、atan2_deg( y, x ) は、2 個の引数を渡すので、少々の工夫が必要です。fn set_widgets7() の改修部を説明します。( 564 から 637 行 )
// 省略
fn set_widgets7(ref mut ui: conrod::UiCell, ids: &mut Ids, text: &mut String, answer: &mut String) {
widget::Canvas::new()
.pad(0.0)
.color(conrod::color::rgb(0.5, 0.9, 0.5))
.set(ids.canvas, ui);
let canvas_wh = ui.wh_of(ids.canvas).unwrap();
// title
widget::Text::new("Trigon_Func Calculuator")
.mid_top_with_margin_on(ids.canvas, 5.0)
.font_size(20)
.color(color::WHITE)
.set(ids.title, ui);
// textbox
for event in widget::TextBox::new(text)
.font_size(15)
.w_h((canvas_wh[0] - 90.) / 2., 30.0)
.mid_left_with_margin_on(ids.canvas, 30.0)
.border(2.0)
.border_color(color::rgb(0.0, 0.8, 0.0))
.color(color::WHITE)
.set(ids.text_box, ui)
{
match event {
widget::text_box::Event::Enter => println!("TextBox {:?}", text),
widget::text_box::Event::Update(string) => *text = string,
}
}
// button
if widget::Button::new()
// .mid_bottom_with_margin_on(ids.canvas, 40.0)
.w_h((canvas_wh[0] - 90.) / 2., 30.0)
.right_from(ids.text_box, 30.0)
.rgb(0.9, 0.99, 0.9)
.border(2.0)
.border_color(color::rgb(0.0, 0.8, 0.0))
.label("atan2_deg !")
.set(ids.button, ui)
.was_clicked()
{
let ltx = text.len();
let ftx = first_word( &text );
let ytxt = &text[0..ftx];
let xtxt = &text[ftx + 1..ltx];
if let Ok(y) = ytxt.parse::<f64>() {
if let Ok(x) = xtxt.parse::<f64>() {
unsafe {
*answer = format!("{:.5}", atan2_deg( y, x ));
}
println!( "atan2_deg( {:.5} , {:.5} ) = {}", y, x, answer );
}
else {
println!("invalid number");
}
}
else {
println!("invalid number");
}
}
// result
widget::Text::new(answer)
.mid_bottom_with_margin_on(ids.canvas, 10.0)
.font_size(20)
.color(color::WHITE)
.set(ids.result, ui);
}
// 省略
同様に、青色部を改修して、atan2_deg 関数用をコーディングしました。
赤色部の let ftx = first_word( &text ); は、',' で、区切られた最初のワードを抜き出すために ',' の位置を調べる関数です。
fn first_word() は、下記のように追加し書きます。( 50 から 60 行 )
// 省略
fn first_word(s: &String) -> usize {
let bytes = s.as_bytes();
for (i, &item) in bytes.iter().enumerate() {
if item == b',' {
return i;
}
}
s.len()
}
// 省略
次に、func に応じて、fn set_widgets() を選択する部分を説明します。( 142 から 174 行 )
// 省略
if func == "sin" {
set_widgets(ui.set_widgets(), ids, &mut spram, &mut answer);
}
else if func == "cos" {
set_widgets2(ui.set_widgets(), ids, &mut spram, &mut answer);
}
else if func == "tan" {
set_widgets3(ui.set_widgets(), ids, &mut spram, &mut answer);
}
else if func == "asin" {
set_widgets4(ui.set_widgets(), ids, &mut spram, &mut answer);
}
else if func == "acos" {
set_widgets5(ui.set_widgets(), ids, &mut spram, &mut answer);
}
else if func == "atan" {
set_widgets6(ui.set_widgets(), ids, &mut spram, &mut answer);
}
else if func == "atan2" {
let ltx = spram.len();
let ftx = first_word( &spram );
if ltx == ftx {
set_widgets7(ui.set_widgets(), ids, &mut spram2, &mut answer);
}
else {
set_widgets7(ui.set_widgets(), ids, &mut spram, &mut answer);
}
}
else {
set_widgets(ui.set_widgets(), ids, &mut spram, &mut answer);
}
// 省略
atan2_deg の場合には、赤色部のごとく、',' 区切りでない時に "1.0,0.0" ( spram2 ) と仮定して、選択しています。
以上で、コードの説明は、完了です。
それでは、ビルドしてみましょう。下記は、build 時のログです。
PS E:.......\trigon_func_gui> cargo build
Compiling winapi-build v0.1.1
Compiling autocfg v1.0.0
Compiling winapi v0.2.8
Compiling log v0.4.11
Compiling cfg-if v0.1.10
Compiling libc v0.2.72
Compiling bitflags v0.9.1
Compiling khronos_api v1.0.1
Compiling winapi v0.3.9
Compiling byteorder v1.3.4
Compiling cc v1.0.58
Compiling rustc-serialize v0.3.24
Compiling lazy_static v1.4.0
Compiling arrayvec v0.4.12
Compiling lazy_static v0.2.11
Compiling backtrace v0.2.3
Compiling rustc-demangle v0.1.16
Compiling piston-float v0.3.0
Compiling fixedbitset v0.1.9
Compiling nodrop v0.1.14
Compiling bitflags v0.8.2
Compiling fnv v1.0.7
Compiling smallvec v0.1.8
Compiling linked-hash-map v0.5.3
Compiling gcc v0.3.55
Compiling find_folder v0.3.0
Compiling xml-rs v0.6.1
Compiling kernel32-sys v0.2.2
Compiling dwmapi-sys v0.1.1
Compiling gdi32-sys v0.1.2
Compiling dbghelp-sys v0.2.0
Compiling shell32-sys v0.1.2
Compiling user32-sys v0.1.3
Compiling num-traits v0.2.12
Compiling num-integer v0.1.43
Compiling num-iter v0.1.41
Compiling piston-viewport v0.3.0
Compiling petgraph v0.4.13
Compiling pistoncore-input v0.18.0
Compiling shared_library v0.1.9
Compiling log v0.3.9
Compiling stb_truetype v0.3.1
Compiling trigon_func_gui v0.1.0 (E:.......\trigon_func_gui)
warning: use of deprecated item 'gcc::Config': gcc::Config has been renamed to gcc::Build
--> build.rs:4:5
|
4 | gcc::Config::new()
| ^^^^^^^^^^^^^^^^
|
= note: `#[warn(deprecated)]` on by default
warning: use of deprecated item 'gcc::Build::new': crate has been renamed to `cc`, the `gcc` name is not maintained
--> build.rs:4:5
|
4 | gcc::Config::new()
| ^^^^^^^^^^^^^^^^
Compiling backtrace-sys v0.1.37
Compiling gl_generator v0.5.5
warning: 2 warnings emitted
Compiling daggy v0.5.0
Compiling stb_truetype v0.2.8
Compiling rusttype v0.2.4
Compiling num-complex v0.1.43
Compiling glutin v0.7.4
Compiling glium v0.16.0
Compiling rand v0.4.6
Compiling num-bigint v0.1.44
Compiling num-rational v0.1.42
Compiling num v0.1.42
Compiling winit v0.5.11
Compiling conrod v0.53.0
Finished dev [unoptimized + debuginfo] target(s) in 1m 01s
PS E:.......\trigon_func_gui>
build.rs で、一部 warning が発生しています。build 時に、warning が出て表示されるのは、理解できるが、cargo run のときにも、表示されるのは、これ如何です。
Top
|