Pythonを爆速にする「Cython」チュートリアル：　C++のコードがライブラリに依存しているとき。準備編

## 概要
**C++** で書いているコードを、どうしても**Python**で呼べる形のライブラリにしたい。
ただ、そこにはCythonという大きな壁が立ちはだかっていた。

これは、[Pythonを爆速にする「Cython」チュートリアル： 基本的な構成編](https://qiita.com/kenmaro/items/95496b92cdfe0ea182ee)　の続きになります。

今回は、cythonizeしたいC++のコードが、何らかのC++ライブラリに依存している時、どうやってcythonizeすればいいか、というところを解説します。今回は準備編です。

コードは「[ここのgithub](https://github.com/kenmaro3/cython_practice)」にあげてあるので、ぜひご覧ください。

そのためには、```setup.py```の編集が必要ですが、そのときに一度Cythonから離れて、CMakeLists.txtをどう書けばそもそもC++のコンパイルが通るのか、を理解すると楽になります。


## 状況説明
以前のフォルダ構成から、名前だけ少し変えて整えました。

```bash
user@~/Documents/cython_practice> tree .
.
├── cpp_library
│   ├── TestClass1.cpp
│   └── TestClass1.h
├── cython
│   ├── my_library.pyx
│   ├── test_class1.pxd
│   └── test_class1.pyx
└── setup.py

2 directories, 6 files
```

おさらいから始めるとすると、

### ```setup.py ```
はC++, cythonのコードをコンパイルして、ライブラリ用のオブジェクトファイルを作るためのファイルです。これを実行することで、pythonから```import my_libarary```とできるようになります。

```setup.py
from setuptools import setup, Extension, find_packages
from Cython.Build import cythonize
from Cython.Distutils import build_ext
from distutils import sysconfig

ext_modules = [
    Extension(
        "my_library", sources=[
            "./cython/my_library.pyx",
            "./cpp_library/TestClass1.cpp"
        ],
        language="c++"
    )
]

setup(
    name = "my_library",
    cmdclass = {"build_ext": build_ext},
    ext_modules= cythonize(ext_modules)
)

```

### ```cpp_library ```
フォルダの中には、自分のC++で書いたライブラリが入っています。目的は、この```TestClass1.cpp, TestClass1.h```をCython化することで、 Pythonから呼べるようにしよう、ということです。

```TestClass1.h
namespace my_library
{
class TestClass1{
    public:
        TestClass1();
        void test_function1();
};    
} // namespace my_library
```


```TestClass1.cpp
#include <iostream>
#include "TestClass1.h"
using namespace std;

namespace my_library{

TestClass1::TestClass1(){};
void TestClass1::test_function1(){
    cout << "printed from cpp function" << endl;
}


}
```

### ```cython ```
フォルダの中には、先ほどのC++で書かれたライブラリをCython化するためのコードが格納されています。```pxd```ファイルはC++のヘッダーファイル、```pyx```はcppファイルのようなものです。

```my_library.pxd
cdef extern from "../cpp_library/TestClass1.h" namespace "my_library":
    cdef cppclass TestClass1:
        TestClass1()
        void test_function1()
```

```my_library.pyx
import cython
cimport cython

include "test_class1.pyx"

def test():
    return TestClass1Cython()

```

```test_class1.pxd
cdef extern from "../cpp_library/TestClass1.h" namespace "my_library":
    cdef cppclass TestClass1:
        TestClass1()
        void test_function1()
```

```test_class1.pyx
import cython
cimport cython

cdef class TestClass1Cython:
    cdef TestClass1* ptr

    def __cinit__(self):
        self.ptr = new TestClass1()

    def __deadaloc(self):
        del self.ptr

    def test_function1_cython(self):
        self.ptr.test_function1()
```

### 以上を準備したら、コンパイル

```bash
 python setup.py install
```

します。実際に、

```bash
(myenv) user@~/Documents/cython_practice> python 
Python 3.6.7 (default, Nov 16 2019, 21:57:19) 
[GCC 4.2.1 Compatible Apple LLVM 10.0.0 (clang-1000.11.45.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import my_library
>>> test = my_library.test()
>>> test.test_function1_cython()
printed from cpp function
```
とでき、cythonize ができていることを確認しましょう。



###cpp_libraryは、あるC＋＋ライブラリに依存している。
という状況で、どうcythonizeするようなsetup.pyを書けば良いか、という問題にぶち当たるかと思います。
今回は、例としてC++で書かれたプログラムが、gmpライブラリに依存しているとします。
gmpライブラリは、

```bash
wget https://gmplib.org/download/gmp/gmp-6.1.2.tar.xz &&\
tar xvf gmp-6.1.2.tar.xz &&\
cd gmp-6.1.2 &&\
./configure --prefix=/usr/local/gmp/6_1_2 &&\
make && make check && make install
```

でコンパイルできます。

今回はここまでで準備が整ったということで、次に

- 実際にgmpをつかって関数を実装、
- CMakeをつかってコンパイル
- cythonizeのためのsetup.py準備

していきたいと思います。


## まとめ
cythonを使ってC++をpythonから呼べるライブラリにしたい時、C++側がライブラリに依存している状況で適切なsetup.pyを書きたい。
そのための準備を整えた。


おわり。