質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Socket.IO

Socket.IOはNode.js上で動くライブラリであり、すべてのブラウザとモバイルデバイスでリアルタイムのアプリを作動させる事を目的としています。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

4回答

3704閲覧

浮動小数点の値のネットワーク通信プログラム

退会済みユーザー

退会済みユーザー

総合スコア0

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Socket.IO

Socket.IOはNode.js上で動くライブラリであり、すべてのブラウザとモバイルデバイスでリアルタイムのアプリを作動させる事を目的としています。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2015/10/16 07:50

昨日rubyとcで規定フォーマットの通信を行う方法を質問したものです。

ruby側はクライアントで小数点の値を格納して送信するので

ruby

1x = 1.33333.to_f 2y = 2.444.to_f 3data = [x,y] 4socket.write(data.pack("d*"))

c側はサーバーとして

c

1char* buf = new char[8]; 2//---bufの生成---// 3 4memset(buf,0,sizeof(char) * 8); 5recv(socket,buf,sizeof(float),0); 6float x = atof(buf); 7 8memset(buf,0,sizeof(char) * 8); 9recv(socket,buf,sizeof(float),0); 10float y = atof(buf);

のように記述していますがうまくいきません。
xとyに0.0000が入ってしまいます。
bufを表示してみてもうまくいきません(中身が空っぽです)
解決方法を教えていただきたいです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

"d*"はRuby内部でfloatではなくdoubleとして変換しているので、xやyにdoubleを使えば同じ環境(OSやコンパイラが一緒)ならうまく取れるかも知れません。なお、取得するbufはdobule *buf = new dobule[2];って感じにして、そのままxやyにぶち込みます。

さて、汎用的にしたい場合ですが、maisumakunさんが書いてあるとおり、実装依存があるためdoubleをそのまま渡すには無理があります。んじゃ文字列にするときはどうするの?便利なのがないのかということで探しました。Marshalを使えばそのままできそうな気がします。
Ruby 2.2.0 リファレンスマニュアル > Marshal フォーマット
Ruby側でMarshal.dumpを使って、C++側で上のフォーマットに基づき解釈すればいけるでしょう。

Ruby

1x = 1.33333 2y = 2.444 3socket.write(Marshal.dump(x) + Marshal.dump(y))

C++

1double x; 2double y; 3char version[2]; 4char type; 5char size; 6char *buf; 7 8// xを取得 9recv(socket, version, sizeof(version), 0); 10if (version[0] != 4 || version[0] != 8) {/* エラー処理 */} 11recv(socket, &type, sizeof(char), 0); 12if (type != 'f') {/* エラー処理 */} 13recv(socket, &size, sizeof(char), 0); 14buf = new char[size + 1]; // nullターミナル分1文字多めに 15recv(socket, buf, sizeof(char) * size, 0); 16buf[size] = '\0'; // nullターミナルを忘れずに 17x = atof(buf); 18delete[] buf; // 解放を忘れずに 19// yを取得 20recv(socket, version, sizeof(version), 0); 21if (version[0] != 4 || version[0] != 8) {/* エラー処理 */} 22recv(socket, &type, sizeof(char), 0); 23if (type != 'f') {/* エラー処理 */} 24recv(socket, &size, sizeof(char), 0); 25buf = new char[size + 1]; // nullターミナル分1文字多めに 26recv(socket, buf, sizeof(char) * size, 0); 27buf[size] = '\0'; // nullターミナルを忘れずに 28y = atof(buf); 29delete[] buf; // 解放を忘れずに

手元では試してないので間違っているところがあるかもしれませんが、ご参考ください。infやnanもatofでは大文字小文字無視らしいので大丈夫だと思います。

投稿2015/10/16 13:54

raccy

総合スコア21733

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

まず本筋で無い部分から。

x = 1.33333.to_f

1.33333は、Floatなので、to_fは不要です。

本筋に戻ります。
エンディアンの話が出ていますが、intel系CPU同士であればエンディアンは同じなので、実行環境が限定されているのであれば、リトルエンディアンのままで大丈夫です。

float x = atof(buf);

atofは文字列からfloatに変換する関数なので、この場合は関係ありません。

C

1float x, y; 2recv(socket,&x,sizeof(float),0); 3recv(socket,&y,sizeof(float),0);

で、おおむね大丈夫です。

厳密には、recvの戻り値を確認して、sizeof(float)より小さい場合は続きの場所に受信するようにします。
戻り値-1の場合(エラー)の対処も必要です。

あと、ちゃんと動くためには、Ruby側では倍精度実数(double)、C側では単精度実数(float)となっているため、どちらかを変更して、型を合わせる必要があります。

投稿2015/10/17 03:06

otn

総合スコア84423

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

... 通信を行う方法...

'RPC ruby "C" ' で google 検索すると良いです。

私としては、JSON 形式で通信するのがお勧めします。

投稿2015/10/16 22:42

katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

浮動小数点数の扱いについては、機種依存な部分が多々あります。

まず、packのd書式は浮動小数の形式・エンディアンについて機種依存となっています。そのため、Ruby側とC側でエンディンが違えばまともに動きません。また、Ruby側では基本的に倍精度で扱っていますので、dで送ったものをfloatで受けても正しい値にはなりません。

よほど性能や通信量に条件があるのでなければ、いったんテキスト化して送るほうがハンドリングもしやすいし、誤解釈の恐れも減るのでいいかもしれません。

投稿2015/10/16 08:07

maisumakun

総合スコア145121

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2015/10/16 08:15

回答ありがとうございます。 やはり文字列にして送ったほうがいいのでしょうか.... なにか方法はないのでしょうか? 文字列にして送る場合はサイズの固定はどうすればいいのでしょう...(16byte文字列とかで送る場合)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問