CythonでPythonのソースコードを秘匿化する

# 要点

Cythonを利用してPythonのソースコード（src）を秘匿化することは可能です。その方法を説明します。

具体的には、.py ファイルをCythonでコンパイルし、バイナリファイル（.pydや.so）に変換することで、元のPythonコードを直接読むことができない状態にします。

---

##  1. なぜCythonでコードを秘匿できるのか？

* Cythonは、PythonコードをC言語コードに変換し、コンパイルします。
* コンパイル後の成果物（`.pyd`や`.so`）はバイナリ形式であり、元のPythonコードは含まれていません。
* これにより、簡単にはソースコードを読まれないように保護できます。

>  **注意点**
> 完全な秘匿（リバースエンジニアリング不可能）は難しいですが、十分に強力な保護となります。

---

##  2. Cythonによるコード秘匿化の基本手順

一般的な流れは以下です。

### ① Cythonをインストール

```bash
pip install cython setuptools wheel
```

### ② フォルダ構造の例（推奨）

```
project-name/
│
├── setup.py
├── README.md
├── requirements.txt
├── LICENSE
│
├── src/
│   └── your_package/
│       ├── __init__.py
│       ├── detection.py
│       ├── utils.py
│       ├── backbones.py
│       └── visualize.py
│
└── build/  # コンパイル後に生成されるフォルダ
```

* `setup.py` を使ってCythonビルドをします。

### ③ setup.py の内容例

```python
from setuptools import setup, Extension
from Cython.Build import cythonize
import numpy

extensions = [
    Extension("your_package.*", ["src/your_package/*.py"]),
]

setup(
    name='your_package',
    ext_modules=cythonize(
        extensions,
        compiler_directives={'language_level': "3"},
    ),
    packages=['your_package'],
    package_dir={'your_package': 'src/your_package'},
    include_dirs=[numpy.get_include()],
)
```

* 上記はフォルダ全体の `.py` をまとめてCython化します。
* 個別に指定する場合は、明示的にファイル名を指定可能です。

### ④ コンパイルの実行方法

```bash
python setup.py build_ext --inplace
```

* これで、元の `.py` ファイルがコンパイルされ、`.pyd`（Windows）または`.so`（Linux/Mac）が生成されます。

* コンパイル後の構造（例）：

```
your_package/
├── __init__.py
├── detection.cp311-win_amd64.pyd
├── utils.cp311-win_amd64.pyd
├── backbones.cp311-win_amd64.pyd
└── visualize.cp311-win_amd64.pyd
```

* 元の `.py` は削除しても実行可能です。

### ⑤ 不要なファイルの削除（秘匿化）

```bash
find src/your_package/ -name "*.py" -delete
find src/your_package/ -name "*.c" -delete
```

（重要なバックアップは必ず取ってから実行してください。）

---

##  3. フォルダ構造の推奨内容の変化

Cythonを導入することで、推奨フォルダ構成が少し変わります：

* ソースコード（`src/`）フォルダの構造は同じですが、**ビルド成果物（`.pyd/.so`）のみを配布対象**にします。
* 配布時は元のPythonファイルを削除または別途保管します。

推奨の最終構造（秘匿化後）は次のようになります。

```
project-name/
│
├── README.md
├── LICENSE
├── requirements.txt
│
├── your_package/                 # コンパイル後のバイナリ
│   ├── __init__.py               # 必須 (空でOK)
│   ├── detection.cp311-win_amd64.pyd
│   ├── utils.cp311-win_amd64.pyd
│   ├── backbones.cp311-win_amd64.pyd
│   └── visualize.cp311-win_amd64.pyd
│
└── setup.py                      # 再コンパイル用
```

* ユーザーにはバイナリのみを配布し、元のPythonコードは配布しません。
* パッケージインストールの際は、上記フォルダをそのまま利用します。

---

##  4. 制限事項と注意点

* `.pyd`や`.so`はPythonのバージョンごとに互換性があります。複数バージョンのPythonで利用する場合は、それぞれのバージョン用にコンパイルする必要があります。(python 3.10, python3.11, python3.12の各バージョアンを用意する。
* 完全にコードを読めなくするわけではなく、高度なリバースエンジニアリングは理論上可能です。機密性の高いコードには、追加で難読化技術（obfuscation）も検討してください。

---

##  5. まとめ（推奨フロー）

* コードを `src` に用意
* Cythonでコンパイルし、`.pyd`や`.so`にする
* 元の `.py` を削除し、バイナリのみ配布
* 配布する際は必ずPythonバージョンを明記する

これでソースコードの秘匿性が大幅に向上します。ぜひ試してみてください。

## 6. 補足資料(pydとsoファイルについて）

CythonでPythonファイルをコンパイルすると、プラットフォームに応じて拡張モジュールとしてバイナリ形式のファイルが生成されます。主に生成されるのは、以下の二種類です。

* `.pyd` ファイル（主にWindows環境）
* `.so` ファイル（主にLinux、macOSなどUnix系環境）


### 1. 拡張モジュールの概要

Pythonで拡張モジュールを作る際、CやC++で記述したコードをPythonで呼び出せるように、動的ライブラリとしてコンパイルします。この動的ライブラリがプラットフォームごとに異なる形式を持ちます。

| OS          | 拡張子    | 説明                     |
| ----------- | ------ | ---------------------- |
| Windows     | `.pyd` | Python用のDLL            |
| Linux/macOS | `.so`  | Shared Object（共有ライブラリ） |


### 2. `.pyd` ファイル（Windowsの場合）

#### 基本的な特徴

* `.pyd` は、WindowsにおいてPythonの拡張モジュールとして使われる特殊なDLLファイルです。
* PythonのC APIを使ってPythonインタプリタとのインタフェースを持ち、通常のDLLとは少し異なり、Pythonインタプリタで直接 `import` 可能な形式となっています。

#### 通常のDLLとの違い

* 通常のDLLと同じくダイナミックリンクライブラリであることには変わりありませんが、`.pyd` ファイルはPythonから直接インポートできる特別な形式をしています。
* 通常のDLLは `ctypes` を利用してロードしますが、`.pyd` は通常のPythonモジュールのように直接インポート可能です。

#### 使用方法の例

```python
import example  # example.pydが存在する場合
example.say_hello()
```

#### 命名規則

* Pythonのバージョンによって名前が決まることがあります（例：`example.cp310-win_amd64.pyd` など）。
* `cp310` はCPython 3.10を意味し、`win_amd64` は64bit Windows用という意味です。

---


### 3. pyd と so の比較まとめ

| 項目       | `.pyd` ファイル (Windows)           | `.so` ファイル (Linux/macOS)                    |
| -------- | ------------------------------- | ------------------------------------------- |
| ファイル形式   | DLL（ダイナミックリンクライブラリ）             | 共有ライブラリ (Shared Object)                     |
| インポート方法  | Pythonで直接 `import` 可能           | Pythonで直接 `import` 可能                       |
| プラットフォーム | Windows                         | Linux, macOS                                |
| 命名規則     | `.cp310-win_amd64.pyd` のような命名規則 | `.cpython-310-x86_64-linux-gnu.so` のような命名規則 |

---

### 4. クロスプラットフォーム対応について

* `.pyd`と`.so`は、プラットフォーム固有のバイナリのため、互換性はありません。
* マルチプラットフォーム対応をする場合、それぞれのOS向けにビルドして提供する必要があります。



## 参考資料
https://qiita.com/kotai2003/items/3b73b45eb46d20a5ce2c