OrangePi Zero2でPythonからGPIOを利用しようとしたら苦労した話

# そもそもの話
RaspberryPiが売ってない！　売ってたとしても高すぎる！

ということから安いSBCを利用しようとした．OrangePiが安いじゃん．ついでにGPIOつかっていろいろ遊ぼう．
GPIOはCとかでも触れるけどPythonで触りたいね．GPIOを触ろうとしたら，OrangePi専用のPythonライブラリがある！OPi.GPIOというのか！

あれれ～，OPi.GPIOをインストールできないぞ～？

# だまされた話（勘違いしていた話）
OrangePiのGPIOを扱うPythonライブラリが複数あるのだけれども，そのなかにはPypiからpipでインストールできるものがある．
OPi.GPIOというのだが，実はこれ，Zero2には非対応．Zero（無印）までなのである．そのままでも使えなくはないけれども，ピン番号の対応を自力で別でしなければいけないからかなり面倒．
今回は素直にZero2に対応したライブラリを入れることにした．
あと今回の解決策，GitのIssueに載ってた

# Zero2対応ライブラリ
対応しているライブラリがOPI.GPIO(https://github.com/eutim/OPI.GPIO)だけどもOrangePi 3とOrangePi Liteも対応しているからこちらで詰まってる人もありかもしれない．

# やり方
まず普通にGitHubからクローンしてくる
```:Linuxコマンド
sudo apt-get update
sudo apt-get install python-dev git
git clone https://github.com/eutim/OPI.GPIO
cd ./OPI.GPIO/source
```
上記は，aptコマンドからアップデートリストを拾ってきて，`git`と`python-dev`をインストールする．環境によっては`python3-dev`っぽい．
gitからクローンしてきて，直下のOPI.GPIOにディレクトリを移動している．

次に，`OPI.GPIO/source`の中のソースコードをいろいろいじっていく．
ちなみに下記の内容は[こっちのGithub](https://github.com/NadavK/OPI.GPIO/pull/1/commits/17080ca240e07eb8f26a7d9a4997460dde061096)に載せてくれてるのでこっちのほうがわかりやすいかも．

`boards.h` `common.h` `constants.h` `py_pwm.h` の4つのファイルの変数宣言している部分にextern宣言を加える．

```c:source/boards.h の23行から30行
extern const int pin_to_gpio_h616[41];
extern const int pin_to_gpio_pi3[41];
extern const int pin_to_gpio_lite2[41];
extern const int pin_to_gpio_zero[41];
extern const int pin_to_gpio_zero2[41];
extern const int pin_to_gpio_pc[41];
extern const int pin_to_gpio_pc2[41];
extern const int pin_to_gpio_prime[41];
```
```c:source/common.h の47行から53行
extern int board_type;
extern int gpio_mode;
extern const int (*pin_to_gpio)[41];

extern int gpio_direction[383];
extern int setup_error;
extern int module_setup;
```
```c:source/constants.h の26行から50行
extern PyObject *high;
extern PyObject *low;
extern PyObject *input;
extern PyObject *output;
extern PyObject *pud_off;
extern PyObject *pud_up;
extern PyObject *pud_down;
extern PyObject *rising_edge;
extern PyObject *falling_edge;
extern PyObject *both_edge;
extern PyObject *unknown;
extern PyObject *board;
extern PyObject *bcm;
extern PyObject *soc;
extern PyObject *version;
extern PyObject *bunknown;
extern PyObject *bzeroh2;
extern PyObject *bzeroh5;
extern PyObject *bzeroplus3;
extern PyObject *bpc;
extern PyObject *bpc2;
extern PyObject *bprime;
extern PyObject *bh616;
extern PyObject *blite2;
extern PyObject *bpi3;
```
`source/soft_pwm.c`の変数宣言にstatic宣言を加える．
```c:source/py_pwm.h の23行
static pthread_t threads;
```
`constants.c`に新しくPyObjectの変数宣言を加える．constants.**h**じゃなくてconstants.**c**だから間違えないように．

```c:source/constants.c の#includeのすぐ下
PyObject *high;
PyObject *low;
PyObject *input;
PyObject *output;
PyObject *pud_off;
PyObject *pud_up;
PyObject *pud_down;
PyObject *rising_edge;
PyObject *falling_edge;
PyObject *both_edge;
PyObject *unknown;
PyObject *board;
PyObject *bcm;
PyObject *soc;
PyObject *version;
PyObject *bunknown;
PyObject *bzeroh2;
PyObject *bzeroh5;
PyObject *bzeroplus3;
PyObject *bpc;
PyObject *bpc2;
PyObject *bprime;
PyObject *bh616;
PyObject *blite2;
PyObject *bpi3;
```
そして，`common.c`の27行目あたりに以下のコードを追記する
```c:source/common.c
const int (*pin_to_gpio)[41];
int gpio_direction[383];
```

そして最後に，ターミナルでインストール
```:Linuxコマンド
cd ../
sudo python setup.py install
```

これで動いた！

# エラーの解説

```
source/c_gpio.c:39:63: warning: --(以下省略
```
「c言語の文法が非推奨な書き方になってるよ」って意味．可読性にかかわる部分なので今回は無視してヨシ！

```Linuxコマンド
/usr/(中略)/OPI.GPIO/source/constants.h:30: multiple definition of `pud_off'; (中略)/source/constants.o:(中略)OPI.GPIO/source/constants.h:30: first defined here
```
c++だと別ファイルで複数の同じ変数を使えるけども，cだとそういうわけにはいかないので，「ここの変数宣言，別の場所で同じ変数名で宣言されてるよ」っていみ．ヘッダーファイルで変数宣言してるのでextern宣言を加えることでこのエラーを回避