Ubuntuを入れて使っていたUSB接続のSSDドライブをほかの用途に使いたい。パーティションを切りなおさなければいけないので、windowsからDISKPARTを使った。DISKPARTはFDISKの後継コマンドらしい。
コマンドプロンプトあるいは名前を指定して実行から、diskpart と入力するとコマンドラインツールが起動する。
① list disk で接続しているドライブをすべて表示
② select disk (ディスク番号) を使って、おそらく操作対象であろう物の番号を指定してアクティブにする。
③ detail disk を実行し、現在アクティブなドライブレターやボリュームラベルなどを確認して、確かに操作対象であることを確認する
④ list partition を使ってこのディスクのパーティションの状態を確認。こうやってしっかり自分が正しいディスクを操作しようとしていることを確認する。
* なお、select disk した後でlist diskすると、現在アクティブなドライブの左側に*がつく。
① select partition (パーティション番号) を使い、現在アクティブなディスクの、操作したいパーティションを選択する。
* この状態で list partitionすると、現在アクティブなパーティションの左側に*がついて見える。
② パーティションを削除するには、delete partition または delete partition override を使用。保護されたパーティションなど、delete partition overrideでなければ削除できないものがある。
* 拡張パーティションは空でないと削除できない。

ので、先に中の論理パーティションを削除してから拡張パーティションを削除する。

① create partition primary により、未割り当て領域いっぱいにプライマリパーティションを作成する。いっぱいにしたくない場合はscreate partition primary size=〇〇 とサイズを指定する。(単位はMB)

② format fs=ntfs により、フォーマットする。恐ろしく時間がかかる。本当に恐ろしく時間がかかるので、format fs=ntfs quick と指定することを強く強く推奨する。一度開始すると中断する方法がないので、quickをつけることを積極的に検討するべきだ。
③ assign letter = (ドライブレター) によりドライブレターを与える。この作業をしないとエクスプローラなどでドライブを認識できない。
use std::rc::Rc; use std::cell::RefCell;
#[derive(Debug)] struct Color{ r:f32, g:f32, b:f32 } impl Color{ fn new(R:f32,G:f32,B:f32)->Color{ return Color{r:R,g:G,b:B}; } }
fn main(){ let value = Rc::new( RefCell::new( Color::new(0.3,0.2,0.1) ) ); let a = Rc::clone(&value); // ポインタを複製 let b = Rc::clone(&value); // ポインタを複製 // borrow_mut()でアクセス // 構造体を上書きする *a.borrow_mut() = Color::new(0.0,0.0,0.0); println!("a: {:?}", a.borrow()); // 構造体の要素を上書きする b.borrow_mut().r=1.0; println!("b: {:?}", b.borrow()); // borrow()では書き込みできない // b.borrow().g = 1.0; }
これもNoneと組み合わせてnullptrのようなものを表現できる。
この時、Rc::strong_countを使うと、有効なポインタの個数を取得できる。
use std::borrow::Borrow; use std::rc::Rc; use std::cell::RefCell; #[derive(Debug)] struct Color{ r:f32, g:f32, b:f32 } impl Color{ fn new(R:f32,G:f32,B:f32)->Color{ return Color{r:R,g:G,b:B}; } } fn main(){ let value = Rc::new( RefCell::new( Color::new(0.3,0.2,0.1) ) ); let mut ref_a = Some(Rc::clone(&value)); // ポインタを複製 let ref_b = Some(Rc::clone(&value)); // ポインタを複製 // 参照の個数を取得 // value , ref_a , ref_b の三つなので3 println!("pointer count: {}",Rc::strong_count(&value)); // 3 ref_a = None; // ref_a を無効にする // ref_a が None なので value , ref_b の二つで2 println!("pointer count: {}",Rc::strong_count(&value)); // 2
if let Some(aa) = ref_a{ *aa.borrow_mut() = Color::new(0.0,0.0,0.0); } else{ println!("ref_a is invalid"); }
if let Some(bb) = ref_b{ *bb.borrow_mut() = Color::new(1.0,1.0,1.0); } else{ println!("ref_b is invalid"); }
// ref_bで書き換えた値が得られる println!("{:?}",value); }
Rc::newでSharedポインタを作り、Rc::downgrade()関数でWeakポインタを作る。
問題は有効性の確認のところで、upgrade()関数がOption<Rc<T>>を返すので、upgrade()の戻り値がSomeを持っている。Someが有効かどうかをチェックするため、if letでパターンマッチする。
use std::rc::{Rc, Weak};
#[derive(Debug)] struct Color{ r:f32, g:f32, b:f32 } impl Color{ fn new(R:f32,G:f32,B:f32)->Color{ return Color{r:R,g:G,b:B}; } }
fn main() { let weak; { // Sharedポインタ let shared = Rc::new(Color::new(0.3,0.5,0.0)); // Weakポインタ作成 weak = Rc::downgrade(&shared); // 所有権を持っているのがsharedなので、ここでsharedは破棄される } // weak.Some が有効なら、変数valueに値が入るので表示する if let Some(value) = weak.upgrade() { // weakが指しているデータを表示 println!("{:?}", value); } else { println!("weakは無効"); } }
Weakポインタの個数を取得できる。weak_count()を呼び出す。
fn main() { let weak; { // Sharedポインタ let shared = Rc::new(Color::new(0.3,0.5,0.0)); // Weakポインタ作成 weak = Rc::downgrade(&shared); // Weakポインタをコピーする let weak2 = weak.clone(); println!("{}",weak.weak_count()); // 有効なWeakの数を得る。2 になる // 所有権を持っているのがsharedなので、ここでsharedは破棄される } println!("{}",weak.weak_count()); // 有効なWeakの数を得る。 0 になる }
Rustでは、変数に対する=式で変数の所有権が移動してしまう。従って、安易に=代入するとmoveが発生してしまいコンパイルできなくなる。
#[derive(Debug)] struct Color{ r:f32, g:f32, b:f32 } impl Color{ fn new(R:f32,G:f32,B:f32)->Color{ return Color{r:R,g:G,b:B}; } } fn main() { let color = Color::new(0.5,0.2,0.0); let ref1 = color; let ref2 = color; // ref1にcolorが入っているのでcolorは空。 println!("{:?}",color); }
これを避けるには参照(&T)を使うか、Rcという参照カウンタを持つスマートポインタを使う。C++でいうところのshared_ptr。
ここで重要な違いだが、
・Rc ... それぞれが所有権を持つ。すべてのRcが破棄された時が変数(の値)の寿命
・&T ... 参照は所有権を持たないので、有効範囲が参照元の変数の寿命に依存する。
Rc::new()でポインタを作成し、clone()で参照を複製する。
use std::rc::Rc; #[derive(Debug)] struct AB{ a:i32, b:i32, } ////////////////////////////////////////////////// fn main( ){ let ref3; { // Sharedポインタ作成 let myref=Rc::new(AB{a:5,b:10}); { // ポインタを複製。値の複製ではない let ab=myref.clone(); println!("{:?}",ab); // 参照カウント println!("Reference Count ab: {}",Rc::strong_count(&ab)); } // ref3は所有権を持つので、 // myrefのスコープが切れても値は破棄されない ref3 = myref.clone(); } println!("Reference Count ref3: {}",Rc::strong_count(&ref3)); // myrefは無効 // ref3 は有効 let k = ref3.a; println!("{}",k); }
Rustにはnullptrがない。Rcが無効であることを表現できないので、Optionと組み合わせる。
Optionは値があればSomeの中に入っている。値がなければNoneを持つ。
use std::{rc::Rc}; #[derive(Debug)] struct Color{ r:f32, g:f32, b:f32 } impl Color{ fn new(R:f32,G:f32,B:f32)->Color{ return Color{r:R,g:G,b:B}; } } ////////////////////////////////////////////////// fn main( ){ let my_color = Color::new(0.5, 0.4, 0.3); // nullptrができないのでOptionと組み合わせる let mut data: Option<Rc<Color>> = None; // Optionなので、Option::Someに値を入れる data = Some(Rc::new(my_color)); if let Some(color) = data{// dataが有効ならcolorを定義して代入 println!("{:?}",color); } else{ println!("nullptr"); } }
Rc::newにメモリ管理を移管するのは簡単だが、その逆はできないらしい。即ち、一度Rcで管理すると決めたら、もう自分で管理できなくなる。
use std::rc::Rc; #[derive(Debug)] struct AB{ a:i32, b:i32, } ////////////////////////////////////////////////// fn main( ){ let ab = AB{a:5,b:10}; let myref=Rc::new(ab);// abからmyrefにmoveするので、以後 ab は使えない println!("{:?}",myref);// ここで ab を使おうとするとビルドエラー }
#include <iostream> #ifdef _DEBUG #pragma comment(lib, "tiffd.lib") #else #pragma comment(lib, "tiff.lib") #endif #include <tiffio.h> #include <vector> #include <cassert> #pragma warning(disable:4996) int main() { // 保存する画像のサイズ std::uint32_t width = 2; std::uint32_t height = 4; // 画像を作成 std::vector<std::uint8_t> mydata(width * height * 3); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { int pos = y * width + x; mydata[pos * 3 + 0] = float(pos) / (width*height) * 255; mydata[pos * 3 + 1] = 0; mydata[pos * 3 + 2] = 0; } } // tiffファイルの書き込み開始 TIFF* out = TIFFOpen("D:\\Data\\test.tif", "w"); TIFFSetField(out, TIFFTAG_IMAGEWIDTH, width); TIFFSetField(out, TIFFTAG_IMAGELENGTH, height); TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, 3); // RGB color TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 8); // Per channel TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT /*ORIENTATION_BOTRIGHT*/); TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);//色の格納方法 RGBRGBRGBかRRRGGGBBBか等 TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);//ピクセルデータの解釈方法 tsize_t scanlinebytes = 3 * width;// mydataのスキャンライン計算 TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(out, scanlinebytes )); for (std::uint32_t row = 0; row < height; row++) { // row 行目の先頭アドレスを取得 uint8_t* ptr = &mydata[0] + row * scanlinebytes; if (TIFFWriteScanline(out, ptr, row, 0) < 0) // 書き込み break; } TIFFClose(out); return 0; }
CMakeはかなり楽。
Where is the source code: D:/myDevelop/mydev/libtiff/libtiff-master
Where to build the binaries: D:/myDevelop/mydev/libtiff/libtiff-sln
CMAKE_INSTALL_PREFIX: D:/myDevelop/mydev/libtiff/libtiff-install
slnを開いて、ALL_BUILD → INSTALL 。
せっかくなのでTIFFTAG_PHOTOMETRIC や TIFFTAG_PLANARCONFIG を取得する例を書いているが使っていないので消していい。
#include <iostream> #ifdef _DEBUG #pragma comment(lib, "tiffd.lib") #else #pragma comment(lib, "tiff.lib") #endif #include <tiffio.h> #include <vector> #include <cassert> #pragma warning(disable:4996) void pnmP3_Write(const char* const fname, const int width, const int height, const unsigned char* const p); int main() { // tiffファイルの読み込み TIFF* tif = TIFFOpen("D:\\Data\\test.tif", "r"); if (tif == nullptr) { std::cout << "Error: Cannot open tiff file" << std::endl; return -1; } // tifデータの情報を取得 std::uint32_t width, height; std::uint16_t bits_per_sample, samples_per_pixel; std::uint16_t photometric; std::uint16_t planar_config; std::uint16_t sample_format; TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width); // 画像の幅 TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height); // 画像の高さ TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bits_per_sample); // 1画素あたりのビット数 TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samples_per_pixel); // 1画素あたりのサンプル数 TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric); // 画像のフォーマット TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &planar_config); // 画像の格納形式 TIFFGetField(tif, TIFFTAG_SAMPLEFORMAT, &sample_format); // 画像のデータフォーマット // 8bitのみ対応 assert(bits_per_sample == 8); // RGBの場合はAは不透明に設定される assert(samples_per_pixel == 3 || samples_per_pixel == 4); size_t image_size = width * height; // 画像を読み込むためのバッファを作成 std::uint32_t* buffer = (std::uint32_t*)_TIFFmalloc(image_size * sizeof(std::uint32_t)); // 画像を保存するためのバッファを作成 std::vector<std::uint8_t> mydata(image_size * 3); // RGBの3チャンネルだけ使用 // 画像を読み込む if (TIFFReadRGBAImage(tif, width, height, buffer, 0)) { for (size_t i = 0; i < image_size; i++) { mydata[i * 3 + 0] = TIFFGetR(buffer[i]); mydata[i * 3 + 1] = TIFFGetG(buffer[i]); mydata[i * 3 + 2] = TIFFGetB(buffer[i]); } } _TIFFfree(buffer); // tiffオブジェクトを解放 TIFFClose(tif); pnmP3_Write("test.ppm", width, height, mydata.data()); std::cout << "Hello World!\n"; } ////////////////////////////////////////////////// ////////////////////////////////////////////////// ////////////////////////////////////////////////// ////////////////////////////////////////////////// //! @brief PPM(RGB各1byte,カラー,テキスト)を書き込む //! @param [in] fname ファイル名 //! @param [in] vmax 全てのRGBの中の最大値 //! @param [in] width 画像の幅 //! @param [in] height 画像の高さ //! @param [in] p 画像のメモリへのアドレス //! @details RGBRGBRGB....のメモリを渡すと、RGBテキストでファイル名fnameで書き込む void pnmP3_Write(const char* const fname,const int width, const int height, const unsigned char* const p) { // PPM ASCII FILE* fp = fopen(fname, "wb"); fprintf(fp, "P3\n%d %d\n%d\n", width, height, 255); size_t channelsize = 3; size_t k = 0; for (size_t i = 0; i < (size_t)height; i++) { for (size_t j = 0; j < (size_t)width; j++) { fprintf(fp, "%d %d %d ", p[k * channelsize + 0], p[k * channelsize + 1], p[k * channelsize + 2]); k++; } fprintf(fp, "\n"); } fclose(fp); }
VTKをCMakeしたときにうっかり出力先を間違えて同じディレクトリにdebug,releaseが混在してしまったが、幸い名前が違っているので区別可能な場合、PowerShellを使ってそれらを区別する。
なお、この手が使えるのは、vtkのlibファイル名が「機能名-バージョンd.lib」の構造をしているからなので、d.libで終わっていれば確実にデバッグ用だと判別できるから。
デバッグファイルで末尾がdで終わるファイル名だけの一覧を取得
Get-ChildItem -Path "d:/lib-files" -Recurse -Filter "*d.lib" | Select-Object -ExpandProperty Name
ただし、これだけなら普通のコマンドプロンプトでもできる。
リリース版の拡張子を除くファイル名はdがつかないので、「d.libで終わらない」という指定が必要。これはPowerShellでなければできない。
Get-ChildItem -Path "d:/lib-files" -Recurse | Where-Object { $_.Name -notlike "*d.lib" } | Select-Object -ExpandProperty Name
上記の応用で、いっそ別の場所にコピーしてしまえる。今後のことを考えるとそのほうが楽。
Get-ChildItem -Path "D:/lib-files" -Recurse -Filter "*d.lib" | ForEach-Object { Copy-Item -Path $_.FullName -Destination "d:/lib-debug" }
これで、D:/lib-files/*.d.lib を d:/lib-debug/ にコピーする。
Get-ChildItem -Path "D:/lib-files" -Recurse | Where-Object { $_.Name -notlike "*d.lib" } | ForEach-Object { Copy-Item -Path $_.FullName -Destination "D:/lib-release" }
anacondaでconda installしようとしたとき、以下のエラーが発生した。
OpenSSLは入っているし、管理者権限でanaconda promptを動かしたりしても効果がなかった。
(py29) C:\Users\myuser>conda install -c conda-forge -c open3d-admin open3d
Collecting package metadata (current_repodata.json): failed
CondaSSLError: OpenSSL appears to be unavailable on this machine. OpenSSL is required to
download and install packages.
Exception: HTTPSConnectionPool(host='conda.anaconda.org', port=443): Max retries exceeded with url: /conda-forge/win-64/current_repodata.json (Caused by SSLError("Can't connect to HTTPS URL because the SSL module is not available."))
以下の二つを、
へコピーする。
あとanaconda promptを再起動したほうがいいかもしれない。
Rustのif let some について(まとめ)。Rustのif let someがわからなかったので色々調べた。
まず、Rustは至る所でコードレベルのパターンマッチが可能。
次に、if letはmatch文のシンタクスシュガーである。
従って、if letは=前後の値のパターンマッチと同時に、変数定義もできる
それで、some はenum Optionの、C++のunionでいうところのメンバ名である
Rustのenumについて学んだ話(1) unionとしての使い方
Rustのenumについて学んだ話(4) Optionはenumで実装されている
従って、if let someは、
① if let 文でパターンマッチを行っている
② パターンマッチで、変数が、Option::Someのバリアントを持っているをチェック
③ パターンマッチの機能で、変数を定義
という視点で捉えられる。

マッチだが、retはOption型なので、これは定数Noneか、Some(値)のどちらかが入っている。if letで「retはSome(v)という形の値が入っているか」をチェックする。そしてもしマッチするなら、変数vを定義し、そこに値を入れる。これは正規表現で、パターンにマッチする文字列を取得するのに似ている。

if let Some は、ifの隣に変数定義に使うletが出てくる上に、未知の関数のように見えるSome()の中にそれまで定義されていなかった変数が突如出現するので、Rust初学者にとってはかなりわかりにくい文法だと思う。
Optionに該当する者は比較的新しいC++でも実装されている。std::optionalとstd::nulloptがそれにあたる。ともあれ、Optionは、戻り値にその関数が本来返す値の他に、値が存在しないことを示すNoneを返すことができるようにする仕組みである。
値が存在しないというのは、例えば「i32の配列の中に条件を満たす値があったら返す」のような処理で、該当する数値がなかった場合は、答えがないことになる。
以下は、値がないことも表せる値をValueOrNotFoundというenumで自前実装した例。
// Optionのまねごとをするために自前実装した、 // 「値がないことを表せる ValueOrNotFound型」 enum ValueOrNotFound{ Value(i32), // i32型のValue NotFound, // 定数 NotFound。結果が見つからなかったときはこれが有効 }
// src中の、最初に見つかったthres以下の値を返す関数 // 戻り値はValueOrNotFound型で返す。これは整数値かNotFound定数のどちらかを入れられる fn Search(src:[i32;5],thres:i32)->ValueOrNotFound{ for &val in src.iter(){ if val <= thres{ return ValueOrNotFound::Value(val); // 見つかった場合、整数値を返す } } return ValueOrNotFound::NotFound; // 見つからない場合、NotFound定数を返す }
fn main() { // 配列を定義 let array = [5,6,7,8,9]; // ある値以下の値を一つ返す let ret = Search(array,3); // 値が入っていたら、vを定義しそれを代入 if let ValueOrNotFound::Value(v) = ret { println!("found {}",v); } else{ println!("not found"); } }
// src中の、最初に見つかったthres以下の値を返す関数 // 戻り値はOption型で返す。これはジェネリックで指定するi32型を取る /* Optionの定義は以下のようになっている。 <T>とジェネリックで型を指定するようになっているのであらゆる型を持てる。 pub enum Option<T> { /// No value. None, /// Some value of type `T`. Some(T), } */ fn Search(src:[i32;5],thres:i32)->Option<i32>{ for &val in src.iter(){ if val <= thres{ return Option::Some(val); // 見つかった場合、整数値を返す } } return Option::None; // 見つからない場合、Noneを返す } fn main() { // 配列を定義 let array = [5,6,7,8,9]; // ある値以下の値を一つ返す let ret = Search(array,3); // 値が入っていたら、vを定義しそれを代入 if let Option::Some(v) = ret { println!("found {}",v); } else{ println!("not found"); } }