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

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

新規登録して質問してみよう
ただいま回答率
85.49%
Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Apache

Apacheは、Apache HTTP Serverの略で、最も人気の高いWebサーバソフトウェアの一つです。安定性が高いオープンソースソフトウェアとして商用サイトから自宅サーバまで、多くのプラットフォーム向けに開発・配布されています。サーバーソフトウェアの不具合(NCSA httpd)を修正するパッチ(a patch)を集積、一つ独立したソフトウェアとして開発されました。

C++

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

Q&A

解決済

2回答

627閲覧

Visual C++でThriftのサンプルを動かしたい

Lopn_

総合スコア50

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Apache

Apacheは、Apache HTTP Serverの略で、最も人気の高いWebサーバソフトウェアの一つです。安定性が高いオープンソースソフトウェアとして商用サイトから自宅サーバまで、多くのプラットフォーム向けに開発・配布されています。サーバーソフトウェアの不具合(NCSA httpd)を修正するパッチ(a patch)を集積、一つ独立したソフトウェアとして開発されました。

C++

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

0グッド

0クリップ

投稿2017/11/01 02:57

編集2017/11/02 06:53

Visual C++でApache Thriftのサンプルを動かしたい

apache.orgからThrift0.9.3のソースコードをダウウンロードし、lib/cppの中Visual C++プロジェクトをビルドしてThriftのスタティックライブラリを作成しました。
そのライブラリを使用してThriftのサンプルを動かそうとしたのですが、リンクエラーが出てしまいビルドすることができません。

使用しているサンプルはこのサイトを参考にして書いたものです。

cpp

1#include <stdio.h> 2#include <iostream> 3 4#include <thrift/protocol/TBinaryProtocol.h> 5#include <thrift/transport/TSocket.h> 6#include <thrift/transport/TTransportUtils.h> 7 8#include "../gen-cpp/TinyCalc.h" 9 10using namespace std; 11using namespace apache::thrift; 12using namespace apache::thrift::protocol; 13using namespace apache::thrift::transport; 14 15using namespace boost; 16 17int main() { 18 boost::shared_ptr<TTransport> socket(new TSocket("localhost", 9090)); 19 boost::shared_ptr<TTransport> transport(new TBufferedTransport(socket)); 20 boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport)); 21 TinyCalcClient client(protocol); 22 23 try { 24 transport->open(); 25 26 double sum = client.sum(1.0, 1.0); 27 std::cout << "1 + 1 = " << sum << std::endl; 28 29 transport->close(); 30 } 31 catch (TException &tx) { 32 std::cout << "ERROR: " << &tx << std::endl; 33 } 34}

thrift

1# TinyCalc.thrift 2 3service TinyCalc 4{ 5 double sum(1: double param1, 2: double param2) 6 double subtract(1:double param1, 2:double param2) 7 double fact(1: i32 param1) 8}

試したこと

libthrift.libとそのヘッダファイルは参照されている。
イメージ説明
追加のインクルードディレクトリはヘッダファイルが置いてあるディレクトリを参照している
src以下はこのような感じにディレクトリがある
イメージ説明
イメージ説明
イメージ説明
イメージ説明
Client.cppには特に赤波線のエラーは出ていない
libファイルはDebug/Releaseで分けてある
イメージ説明
上図のReleaseディレクトリの中身
イメージ説明

エラー内容

イメージ説明

開発環境

Visual Studio 2017 Community

追記

gen-cpp内はこのようになっています。
イメージ説明

cpp

1//TinyCalc.h 2ifndef TinyCalc_H 3#define TinyCalc_H 4 5#include <thrift/TDispatchProcessor.h> 6#include <thrift/async/TConcurrentClientSyncInfo.h> 7#include "TinyCalc_types.h" 8 9 10 11#ifdef _WIN32 12 #pragma warning( push ) 13 #pragma warning (disable : 4250 ) //inheriting methods via dominance 14#endif 15 16class TinyCalcIf { 17 public: 18 virtual ~TinyCalcIf() {} 19 virtual double sum(const double param1, const double param2) = 0; 20 virtual double subtract(const double param1, const double param2) = 0; 21}; 22 23 24.... 25

TinyCalc_types.hは必要な値を入れていないので使われません

これらのコードはthriftで自動的に作成されるコードです。

TinyCalcの部分をコメントアウトしたものがこちらです

cpp

1#include <stdio.h> 2#include <iostream> 3 4#include <thrift/protocol/TBinaryProtocol.h> 5#include <thrift/transport/TSocket.h> 6#include <thrift/transport/TTransportUtils.h> 7 8//#include "../gen-cpp/TinyCalc.h" 9 10 11using namespace std; 12using namespace apache::thrift; 13using namespace apache::thrift::transport; 14using namespace apache::thrift::protocol; 15 16using namespace boost; 17 18int main() { 19 boost::shared_ptr<TTransport> socket(new TSocket("localhost", 9090)); 20 boost::shared_ptr<TTransport> transport(new TBufferedTransport(socket)); 21 boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport)); 22 /* 23 TinyCalcClient client(protocol); 24 25 try { 26 transport->open(); 27 28 double sum = client.sum(1.0, 1.0); 29 std::cout << "1 + 1 = " << sum << std::endl; 30 31 transport->close(); 32 } 33 catch (TException &tx) { 34 std::cout << "ERROR: " << &tx << std::endl; 35 }*/ 36 37 return 0; 38}

thriftとboostしか使用していませんが、リンクエラーが出ます。
boostはNugetからインストール済みです。
エラー内容はこちらです。
イメージ説明

これらのソースはgithubにアップロードしてあります

2017 11/2 15:14 追記

使用するThriftをThrift0.9.3ではなく最新のThrift0.10.0に変えて、TProtocol.cppをプロジェクトに追加
そのlibを対象のプロジェクトで参照したところ、Thriftのみのソースではビルドができました。↓

cpp

1#include <thrift/protocol/TBinaryProtocol.h> 2#include <thrift/transport/TSocket.h> 3#include <thrift/transport/TTransportUtils.h> 4 5using namespace std; 6using namespace apache::thrift; 7using namespace apache::thrift::transport; 8using namespace apache::thrift::protocol; 9 10using namespace boost; 11 12int main() { 13 boost::shared_ptr<TTransport> socket(new TSocket("localhost", 9090)); 14 15 return 0; 16}

この時、Nugetからインストールされてるはずのboostが何故か参照されないエラーが発生したので、Nugetからでなく自分でビルドしたboostを使用したところ、エラーを吐かなくなりました。

thriftでコンパイルしたTinyCalcをビルドしてみろという指摘があったのでスタティックライブラリとしてビルドした後、libthrift.libと同じように参照し以下のソースを書いてビルドしてみました

cpp

1#include <stdio.h> 2#include <iostream> 3 4#include <thrift/protocol/TBinaryProtocol.h> 5#include <thrift/transport/TSocket.h> 6#include <thrift/transport/TTransport.h> 7#include <thrift/transport/TTransportUtils.h> 8 9#include <TinyCalc.h> 10 11using namespace std; 12using namespace apache::thrift; 13using namespace apache::thrift::protocol; 14using namespace apache::thrift::transport; 15 16using namespace boost; 17 18int main() { 19 boost::shared_ptr<TTransport> socket(new TSocket("localhost", 9090)); 20 boost::shared_ptr<TTransport> transport(new TBufferedTransport(socket)); 21 boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport)); 22 TinyCalcClient client(protocol); 23 24 try { 25 transport->open(); 26 27 double sum = client.sum(1.0, 1.0); 28 std::cout << "1 + 1 = " << sum << std::endl; 29 30 transport->close(); 31 } 32 catch (TException &tx) { 33 std::cout << "ERROR: " << &tx << std::endl; 34 } 35}

すると、今度はSSLSocketでリンクエラーが発生しました。
このSSLSocketは使う機会がほとんどなく、別のものに依存しないので、ThriftのプロジェクトからSSLSocketのみを外してビルドし、そのlibを使って上記のコードをビルドしたところ、リンクエラーが発生することもなくビルドが成功しました。

Thriftのクライアント側のビルドが成功したのでサーバ側のソースを同じ環境でビルドしたのですが、そちら側は失敗してしまいました。

サーバ側のソースコードはこちらです

cpp

1#include <TinyCalc.h> 2#include <thrift/protocol/TBinaryProtocol.h> 3#include <thrift/server/TSimpleServer.h> 4#include <thrift/transport/TServerSocket.h> 5#include <thrift/transport/TBufferTransports.h> 6 7using namespace ::apache::thrift; 8using namespace ::apache::thrift::protocol; 9using namespace ::apache::thrift::transport; 10using namespace ::apache::thrift::server; 11 12using boost::shared_ptr; 13 14class TinyCalcHandler : virtual public TinyCalcIf { 15 public: 16 TinyCalcHandler() { 17 // Your initialization goes here 18 } 19 20 double sum(const double param1, const double param2) { 21 // Your implementation goes here 22 printf("sum\n"); 23 24 return param1 + param2; 25 } 26 27 double subtract(const double param1, const double param2) { 28 // Your implementation goes here 29 printf("subtract\n"); 30 31 return param1 - param2; 32 } 33 34}; 35 36int main(int argc, char **argv) { 37 int port = 9090; 38 shared_ptr<TinyCalcHandler> handler(new TinyCalcHandler()); 39 shared_ptr<TProcessor> processor(new TinyCalcProcessor(handler)); 40 shared_ptr<TServerTransport> serverTransport(new TServerSocket(port)); 41 shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory()); 42 shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory()); 43 44 TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory); 45 server.serve(); 46 return 0; 47}

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

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

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

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

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

LouiS0616

2017/11/01 03:55

具体的にどこまで設定を終えられたのでしょうか。パット見る限り、依存ライブラリが追加されていないように見えます。
Lopn_

2017/11/01 13:33

ライブラリの追加とは、そのプロジェクトのプロパティにあるリンカー > 入力の追加の依存ファイルのところに使用するlibファイルを追記するということでしょうか??
LouiS0616

2017/11/01 13:43 編集

その通りです。 『外部シンボルが未解決』というリンクエラーは、『追加の依存ファイル』が不足しているときに見る典型的なエラーです。しかし、更新後の質問を見る限り、少なくとも一発でわかるような不足はありませんでした。
LouiS0616

2017/11/01 13:52 編集

私はThriftを触ったことがないので当てずっぽうで申し訳ないのですが、TinyCalcクラス(あるいは名前空間?)内部の関数の実装を書かなければいけないのでは?
LouiS0616

2017/11/01 13:53

よく考えたら、プロトタイプ宣言だけ書いて実装してない場合もリンクエラーになります。たぶんそれでしょうね。
Lopn_

2017/11/01 14:01

実装の書き方がよくわからず、TinyCalc.hにその旨の記述があるかわからりません。申し訳ありません。質問に追記させていただきました。
Lopn_

2017/11/01 14:06

先ほど試したのですが、TinyCalcの部分をすべてコメントアウトした状態でビルドをしたのですが同じようにリンクエラーが発生しました。libファイルを作成するときにおかしくなっているということは考えられませんか?
LouiS0616

2017/11/01 14:08

コメントアウトした『TinyCalcの部分』とは具体的にどこでしょうか?また、リンクエラーのメッセージは全く同じでしょうか?
LouiS0616

2017/11/01 14:09

ただのビルドだとゴミデータが残ってしまう恐れがあるので、リビルドしてみてください。
LouiS0616

2017/11/01 14:14

あとは、TinyCalc.cpp内でTinyCalcClientの各メンバ関数が実装されているのかも知りたいところです。
LouiS0616

2017/11/01 14:51

ちゃんと実装してあるように見えますね。やはりThriftの使い方に関する問題のようですので、これ以上はちょっとわからないです。
Lopn_

2017/11/01 14:52

そうですか... もう少しいろいろ試してみます。 長い時間ありがとうございました。
guest

回答2

0

自己解決

Apache ThriftをVisual Studioでビルドしようとすると、そもそもvsprojがエラーで使えないため、自分で再構成しなければいけませんでした。

なお、Thrift0.9.3以下のバージョンのライブラリをWindows環境で使用する際、exeファイルにthriftのライブラリをリンクした段階でopenssl1.0.2の未解決参照エラーが発生し、ビルドが通りません。
上記の問題は解決できませんでしたが、Thrift0.10.0以降のバージョンではopenssl1.1.0を使用するようになり、この問題がないためそちらを使うことにしました

Viaual StudioでビルドできるプロジェクトをGitHubに公開したので活用してください
https://github.com/okanon/thrift

投稿2019/05/16 14:16

編集2019/05/16 14:18
Lopn_

総合スコア50

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

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

0

プロジェクトを見てみましたがTinyCalcClientはgen-cpp内にできているのでそれもコンパイルしてリンクするとかしてください。
あと、Thrift\src\thrift\protocol\TProtocol.cppがlibthiftプロジェクトから除外されていてビルドされていません。

original_thrift内に元のthriftが入っています。 これだとエラーでビルドできなかったので、SSLの部分と元から入っていないThrift.cppをソリューションから削除してビルドしています

これをやめてきちんとビルドしたほうがいいと思います。

投稿2017/11/01 15:24

hmmm

総合スコア818

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

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

Lopn_

2017/11/02 06:46

思考錯誤の末、Thriftのクライアント側はビルドできたのですが、同じ参照でサーバ側を作成してビルドしたところ、リンクエラーが発生しました。 サーバ側にもSSLSocketが使われている訳では無いので、追記にあるSSLSocketをプロジェクトから除外したことが原因では無いようです。 SSLSocketを追加してビルドしたところ、サーバ側のソースでもSSLSocketのリンクエラーが発生しました。 SSLSocketには、openssl.dllとlibcrypto.dllが必要なようなのですが、それはディレクトリにあるだけでなく参照しないといけないのですか?
hmmm

2017/11/02 11:39

リンクエラーは関数などの定義(関数の実装)がないというエラーです。なので考えるべきことはcppファイルが足りないかリンクするlibファイルが足りないかです。 opensslに依存しているというのであれば当然opensslのlibファイルが必要です。適当にcppファイルを除外してビルドしているように思えたので、全部きちんとビルドしたほうがいいと書きました。 SSLSocketを外したいのなら、外した状態でのサーバ側のリンクエラーで何が足りていないのかを確認してください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問