私はEclipse(実際にはザイリンクスSDKですが、Eclipseに基づいています)とg ++ 4.9.2を設定して、スタンドアロンASIOを使用するプロジェクトをコンパイルし、プロパティ-> C/C++ビルド->で-std = c ++ 11を使用しました設定->ツール設定->その他のフラグ。すべてのC++ 11機能を使用してコンパイルできます。
また、C/C++ General SymbolsでASIO_HAS_STD_THREAD, ASIO_STANDALONE
などを設定し、ASIOヘッダーがpthread
ではなくstd::thread
を使用することを期待しています。ただし、makeからのエラーが引き続き表示されます。
undefined reference to pthread_create,
..asio-1.10.6\include\asio\detail\impl\posix_thread.ipp
and posix_tss_ptr.hpp
したがって、問題は、C++ 11を使用していて、ASIO_HAS_STD_THREAD
を指定してASIO_HAS_PTHREADS
を指定していないため、posix_thread.ipp
は(posix_thread.hppを介して)含めないでください。 ASIOの.hpp:
#if !defined(ASIO_HAS_THREADS)
# include "asio/detail/null_thread.hpp"
#Elif defined(ASIO_WINDOWS)
# if defined(UNDER_CE)
# include "asio/detail/wince_thread.hpp"
# else
# include "asio/detail/win_thread.hpp"
# endif
#Elif defined(ASIO_HAS_PTHREADS)
# include "asio/detail/posix_thread.hpp"
#Elif defined(ASIO_HAS_STD_THREAD)
# include "asio/detail/std_thread.hpp"
#else
# error Only Windows, POSIX and std::thread are supported!
#endif
ほとんどの人が信じているのとは反対に、C++ 11は-pthread
を必要とせず、Eclipseで-pthread
なしの単純なプロジェクトをコンパイルしようとしました。しかし、私が間違っていれば私を訂正することができます。リンカオプションに-pthread
を入れるとコンパイルできますが、必要がない場合はpthreadを使用したくないと感じました。
Posix_tss_ptr.hppを検索すると、Makefile.amにも見つかりました。これがエラーに影響するかどうか?
では、問題の原因は何ですか?上記の2つの容疑者でない場合は?私の推論が正しい場合はpthreadを使用せずに、ソリューションがまだ純粋なC++ 11の方法を使用できることを願っています.
ASIO_HAS_PTHREADSは私が定義したのではなく、ASIOがどこかでPOSIXスレッドを使用し、リンカーがオプション-pthreadを必要とするのはそのためです。次に、#errorディレクティブを使用してasio/detail/signal_blocker.hppまでトレースしました。定義されている場所は2つだけで、ASIO config.hppにあります。
# if defined(ASIO_HAS_BOOST_CONFIG) && defined(BOOST_HAS_PTHREADS)
# define ASIO_HAS_PTHREADS 1
# Elif defined(_POSIX_THREADS)
# define ASIO_HAS_PTHREADS 1
ASIOは、POSIX THREADSまたはWindowsで、以下に示すsignal_blocker.hppを引き続き応答します。 ASIOがpthreadを必要とするのはそのためです。
#if !defined(ASIO_HAS_THREADS) || defined(ASIO_WINDOWS) \
|| defined(ASIO_WINDOWS_RUNTIME) \
|| defined(__CYGWIN__) || defined(__SYMBIAN32__)
typedef null_signal_blocker signal_blocker;
#Elif defined(ASIO_HAS_PTHREADS)
typedef posix_signal_blocker signal_blocker;
#endif
そして、_PTHREADSは、gnuクロスコンパイラ(arm-xilinx-linux-gnueabi)のインクルードファイル(features.h、posix_opt.hなど)から定義されています。マクロを実際に定義したのは追跡しませんが、ASIOはマクロです。 _POSIX_THREADSを使用するソース。したがって、リンカーオプション-pthreadが存在する必要があります。
繰り返しになりますが、非ASIO C++ 11スレッドではg ++ 4.9.2の-pthreadは必要ありませんが、スタンドアロンASIOでは必要です。次のコードは、g ++ 4.9.2(EclipseベースのザイリンクスSDK)で-pthreadなしで正しくビルドされています。
#include <thread>
void test() {
for(int i=0;i<100;i++);
}
int main()
{
std::thread thread1(test);
thread1.join();
return 0;
}
プログラムがC++ 11で記述されているという事実は、pthread
ライブラリとリンクする必要があるかどうかには関係ありません。 Posixスレッドが必要な場合は、そのライブラリをリンクする必要があります。
C++ 11はstd::thread
クラスを提供し、準拠する各コンパイラの標準ライブラリは、ターゲットシステムがホストするいくつかのネイティブスレッドAPIを使用して、そのクラスの機能を実装する必要があります。 GCCはpthreads
を使用してそれを実装するため、std::thread
とリンクしない限り、GCCで-pthread
オブジェクトを作成するプログラムを構築することはできません。この事実はasio
とは関係ありません。
[〜#〜]後で[〜#〜]
私は実際に-std = c ++ 11だけを使用してstd :: stdを使用してpthreadなしでプログラムをビルドしました
GCCの一部のWindowsポートがデフォルトでlibpthread
にリンクしているという事実に誤解され、混乱していると思います。例えば。サンプルプログラムがthread.cpp
にある場合、TDM-GCC 4.9.2を使用してWindowsで正常にビルドできます。
>g++ -std=c++11 -o test_thread thread.cpp
しかし、冗長モードでビルドした場合:
>g++ -v -std=c++11 -o test_thread thread.cpp
非常に多くのライブラリオプションが舞台裏でリンカーに渡されていることがわかります。特に-lpthread
:
>g++ -v -std=c++11 -o test_thread thread.cpp 2>&1 | grep -Po 'pass-through=-lpthread' -
pass-through=-lpthread
Linuxでは、次の質問がない限り、libpthread
はリンクしません。
$ g++ -std=c++11 -o test_thread thread.cpp
/tmp/ccpyEles.o: In function `std::thread::thread<void (&)()>(void (&)())':
thread.cpp:(.text._ZNSt6threadC2IRFvvEJEEEOT_DpOT0_[_ZNSt6threadC5IRFvvEJEEEOT_DpOT0_]+0x7d): undefined reference to `pthread_create'
collect2: error: ld returned 1 exit status
コードの実行中は、g ++ ssss(コード名)を使用します。cpp-std = c ++ 11 -pthread
それが動作します
ASIOから掘り出したものを以下に示します。最初に簡単な例を示します。 CentOS 6.5 32ビット、およびEclipseでは、g ++ 4.9.3を使用すると、次のコードは-std = c ++ 11のみでビルドされ、-lpthreadと言う必要はありません。
std::string make_greeting_string()
{
auto now = std::chrono::system_clock::now();
const auto in_time_t = std::chrono::system_clock::to_time_t(now);
std::stringstream ss;
//ss << std::put_time(std::localtime(&in_time_t), "%Y-%m-%d %X");
ss << "Greetings"<<45;
return ss.str();
}
int main() {
std::thread thread1(make_greeting_string);
//test2();
thread1.join();
cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
return 0;
}
Tes2()をメインに追加すると、失敗します`pthread_create 'への未定義の参照
void *PrintHello(void *threadid)
{
long tid;
tid = (long)threadid;
std::cout<<"Hello World! It's me, thread #%ld!"<<tid<<std::endl;
pthread_exit(NULL);
}
void test2()
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
for(t=0;t<NUM_THREADS;t++){
std::cout<<"In main: creating thread %ld"<<t<<std::endl;
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc){
std::cout<<"ERROR; return code from pthread_create() is "<<rc<<std::endl;
exit(-1);
}
}
}
まず、スタンドアロンASIOにはposixスレッドを使用するコードがありますが、stdも使用できます。両方が定義されている場合は、最初にstdを使用するように順序を変更する必要があります。 static_mutex.hppの27行目のコード例
#Elif defined(ASIO_HAS_PTHREADS)
#include "asio/detail/posix_static_mutex.hpp"
#Elif defined(ASIO_HAS_STD_MUTEX_AND_CONDVAR)
#include "asio/detail/std_static_mutex.hpp"
次に、posixを必要とするファイルが2つあります:signal_blocker.hppとtss_ptr.hppです。 WindowsとPOSIXのみがサポートされているため、makeは失敗します
2つのファイルを完全に書き直してc ++ 11を使用することが可能かどうかはわかりませんが、これらの2つのファイルは、std :: threadではなく、-lpthreadへの依存関係のソースです。
tss_ptr.hpp
は、ASIO_HAS_THREAD_KEYWORD_EXTENSION
が定義されているため、pthreadは必要ありません。これをシンボルで定義すると、makeエラーは半分になり、signal_blocker.hpp
はこの依存関係のソースです。
signal_set_service.ippに影響します
case asio::io_service::fork_child:
if (state->fork_prepared_)
{
asio::detail::signal_blocker blocker;
close_descriptors();
open_descriptors();
int read_descriptor = state->read_descriptor_;
state->fork_prepared_ = false;
lock.unlock();
reactor_.register_internal_descriptor(reactor::read_op,
read_descriptor, reactor_data_, new pipe_read_op);
}
break;
そしてselect_reactor.ipp
{
#if defined(ASIO_HAS_IOCP)
asio::detail::signal_blocker sb;
thread_ = new asio::detail::thread(
bind_handler(&select_reactor::call_run_thread, this));
#endif // defined(ASIO_HAS_IOCP)
}