Visual Studio で pthread を使いたい

# Visual Studio の NuGet で pthread を使いたい

「NuGet 使えばWindows でも pthread を簡単に使えるよ」 
という甘い言葉に踊らされました
わりかし苦戦したので備忘録を残します。

結論から言うとNuGet使わなくてもいいんじゃないかと

## 1. NuGet で pthread をインストールする

VisualStudioで適当なC/C++プロジェクトを開く
プロジェクト > NuGet パッケージの管理
参照タブを開いて "pthread" と検索
ボタンを押してインストールする

画像のような感じになればOK
![NuGetインストール](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357733/3cae3aca-bbee-154f-e3c7-7688bd8bba74.png)

## 2. プリプロセッサの定義を追加する

NuGetインストール状態でpthread関数を使ったサンプルプログラムをビルドしてみましょう。

■ サンプルプログラム

```c:pthread_win.c
#include <stdio.h>
#include <pthread.h>

void *sleep(void* arg)
{
	// do something
	return 0;
}

int main()
{
	printf("hello world");
	pthread_t handle;  // Thread handle.

	pthread_create(&handle, NULL, sleep, NULL);
	pthread_join(handle, NULL);
}
```

この状態でビルドすると下記のようなエラーが出力されます

> エラー	C2011	'timespec': 'struct' 型の再定義	

これは pthread.h 内と time.h の 両方で timespec 構造体が宣言されているために発生する問題です。

これを解決するための一番簡単な解決方法が 
pthread.h のインクルード前に #define を追加するものです。
定義を追加してみましょう。

※補足
下記サイトに記載がありますが、コンパイルオプションでやる方法もあります。
手順簡略化のためここではソースコードに直defineという手段を取っています。

[Timespec :struct type Error c2011 - Stack Overflow](https://stackoverflow.com/questions/33114535/timespec-struct-type-error-c2011/33733667)

■ 修正後

```c:pthread_win.c
#include <stdio.h>
#define HAVE_STRUCT_TIMESPEC // [Add] 
#include <pthread.h>

void *sleep(void* arg)
{
	// do something
	return 0;
}

int main()
{
	printf("hello world");
	pthread_t handle;  // Thread handle.

	pthread_create(&handle, NULL, sleep, NULL);
	pthread_join(handle, NULL);
}
```

## 4. pthreadvc2.lib をリンクしよう

 定義の追加でいけるかと思いきや今度はこんなエラーが出力されます。

> エラー	LNK2019	未解決の外部シンボル __imp_pthread_join が関数 main で参照されました。	pthread_win	
> エラー	LNK2019	未解決の外部シンボル __imp_pthread_create が関数 main で参照されました。	pthread_win	

そろそろ疲れてくるころですね。

Stack Overflow に記載があるのですが、
NuGet の pthread パッケージには pthreadvc2.lib なるものが欠けているそうです。

[VS2017 Nuget pthread LNK1120 unresolved - Stack Overflow](https://stackoverflow.com/questions/60965741/vs2017-nuget-pthread-lnk1120-unresolved)

こちらでは余分な設定をしなくても済むように、
全プロジェクトから参照できる場所?にライブラリを追加していますね。

`C:\Program Files (x86)\Microsoft Visual Studio\2017\xxxxx\VC\Tools\MSVC\xxxx.xx.xxxx\lib\x86 or x64`

ただ、そこまでやるなら、関連ファイルもまとめて格納したい気が。
例)
[【VC++】スレッド（pThread）を利用する : 全ては時の中に](http://blog.livedoor.jp/akf0/archives/51595429.html)


ということで手間は増えますが、ここではライブラリを個別にリンクしましょう。

### 4.1. Pthread_win32 ライブラリをダウンロードする

下記のサイトからpthreads-w32-2-9-1-release.zipをダウンロードします
https://sourceware.org/pthreads-win32/

### 4.2. pthreadvc2.lib を配置する

ダウンロードしたファイルから、Visual Studioのプロジェクトにあった `pthreadVC2.lib` を抜き出します。
プロジェクトのソリューション構成とプラットホームを確認しましょう。
私の環境では Debug / x86 でした

![ソリューション構成](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357733/0034fea5-bd19-1680-29b1-ae6963d2b089.png)


Debug / x86 であれば ↓のライブラリがプロジェクトにあったライブラリとなります。
`pthreads-w32-2-9-1-release\Pre-built.2\lib\x86\
pthreadVC2.lib`

`pthreadVC2.lib` を 先ほど作成した `pthread_win.c` と同じ場所に配置します。

※補足
ライブラリディレクトリを追加する手順を記載するのが手間なので、
ソースファイルと同じ場所に pthreadVC2.lib を配置しています。
・リンクするライブラリをフルパスで指定する
・ライブラリディレクトリを追加する
ことで任意の場所に配置したライブラリとリンクさせることが出来ます。


### 4.3 pthreadVC2.lib を追加の依存ファイルに追加する

ライブラリを明示的にリンクする必要があります。
プロジェクトを右クリック > プロパティ > 構成プロパティ > 入力 > 
追加の依存ファイルに `pthreadVC2.lib` を追加しましょう。

![link_lib.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357733/d670af25-888b-5031-d3c7-f154fcbe6040.png)

## 5. デバッグ実行には dll ファイルも必要です。

4までの手順でビルドができるようになったはずです。
試しにビルドしてみましょう。

Visual Studio > ビルド > ソリューションのリビルド

出来ましたか?

しかし、今のままデバッグ実行を行おうとするとエラーが出ます

>pthreadVC2.dll が見つからないため、コードの実行を続行できません。
>プログラムを再インストールすると、この問題が解決する可能性があります。

実行時のライブラリが足らんらしいですね。

先ほど使った `pthreads-w32-2-9-1-release` からDLLを持ってきます。
私の環境は Debug / x86 だったので
`pthreads-w32-2-9-1-release\Pre-built.2\dll\x86` の中に入っている dll ファイルを `(ソリューションファイルの場所)\Debug` にコピーします。

これでデバッグ実行もできるようになったはず。

## まとめ
簡単とは一体
NuGetを使う意味はどこに