最近在臉書看到有人提到 py2c 這個程式 (是一個 bash script), 它可以將 Python 程式翻成 C++ 程式, 然後就可以用 C++ 編譯器編譯成可執行檔, 其大小比用 pyinstaller 打包還要小得多, 且可以增加逆向工程還原的難度. 我根據下面這篇文章在 Mapleboard 的 Ubuntu Linux 作業系統下測試時卻出現 "Python.h : 沒有此一檔案或目錄的問題" 錯誤, 尚不知原因, 先把過程記下來.
1. 安裝 Cython3 :
one@LX2438:~$ sudo apt install cython3
正在讀取套件清單... 完成
正在重建相依關係... 完成
正在讀取狀態資料... 完成
建議套件:
cython-doc
下列【新】套件將會被安裝:
cython3
升級 0 個,新安裝 1 個,移除 0 個,有 152 個未被升級。
需要下載 1,306 kB 的套件檔。
此操作完成之後,會多佔用 6,393 kB 的磁碟空間。
下載:1 http://ports.ubuntu.com jammy/universe arm64 cython3 arm64 0.29.28-1ubuntu3 [1,306 kB]
取得 1,306 kB 用了 3s (492 kB/s)
選取了原先未選的套件 cython3。
(讀取資料庫 ... 目前共安裝了 288142 個檔案和目錄。)
正在準備解包 .../cython3_0.29.28-1ubuntu3_arm64.deb……
解開 cython3 (0.29.28-1ubuntu3) 中...
設定 cython3 (0.29.28-1ubuntu3) ...
2. 下載 py2c :
到 GitHub 下載 py2c 這個 bash script :
此程式內容如下 :
#!/bin/bash
if [ -z $1 ];then
printf "Usage: \n\t$0 [python source file][swtich] 1: To C code 2: to bytecode 3: to C and bytecode\n"
exit 0
fi
source_file=$1
tag=$2
fn_ext=$(echo ${source_file} | awk -F '.' '{print $2}'| tr -d '\r\n')
if [ -z ${fn_ext} ]; then
fn=${source_file}
elif [ ${fn_ext} == "py" ]; then
fn=$(echo ${source_file} | awk -F '.' '{print $1}')
fi
if [ ${tag} -eq 1 ]; then
printf "Transfer python source to C.\n"
cython3 --embed -o ${fn}.c ${source_file}
elif [ ${tag} -eq 2 ]; then
printf "Transfer python source to bytecode.\n"
gcc -Os -I /usr/include/python3.6m -o ${fn} ${fn}.c -lpython3.6m -lpthread -lm -lutil -ldl
elif [ ${tag} -eq 3 ]; then
printf "Transfer python source to C sode and bytecode\n"
cython3 --embed -o ${fn}.c ${source_file}
gcc -Os -I /usr/include/python3.6m -o ${fn} ${fn}.c -lpython3.6m -lpthread -lm -lutil -ldl
fi
printf "Transfer End\n"
將此程式貼到 nano 存成 py2c 檔 :
one@LX2438:~$ nano py2c
用 chmod 指令將其權限改為可執行檔後複製到 /usr/bin/local 下 :
one@LX2438:~$ chmod 777 py2c
one@LX2438:~$ cp py2c /usr/local/bin
輸入 py2c 會顯示程式用法 :
one@LX2438:~$ py2c
Usage:
/usr/local/bin/py2c [python source file][swtich] 1: To C code 2: to bytecode 3: to C and bytecode
亦即指令的格式為 :
py2c 原始程式.py 選項
選項的值有 1, 2, 3 三個, 1 是將 Python 程式轉成 C 程式; 2 是轉成可執行的 byte code; 3 是轉成 C 程式與可執行的 byte code.
所以我寫了一個 Python 測試程式 helloworld.py :
#helloworld.py
print('Hello World!)
但執行 py2c 卻出現錯誤 :
one@LX2438:~$ py2c helloworld.py 3
Transfer python source to C sode and bytecode
/home/one/.local/lib/python3.10/site-packages/Cython/Compiler/Main.py:369: FutureWarning: Cython directive 'language_level' not set, using 2 for now (Py2). This will change in a later release! File: /home/one/helloworld.py
tree = Parsing.p_module(s, pxd, full_module_name)
helloworld.c:6:10: fatal error: Python.h: 沒有此一檔案或目錄
6 | #include "Python.h"
| ^~~~~~~~~~
compilation terminated.
Transfer End
我找到下面這篇文章 :
說是要安裝 python3-dev 才行, 但我安裝後還是一樣 :
one@LX2438:~$ sudo apt-get install python3-dev
正在讀取套件清單... 完成
正在重建相依關係... 完成
正在讀取狀態資料... 完成
python3-dev 已是最新版本 (3.10.6-1~22.04)。
python3-dev 被設定為手動安裝。
目前暫時無解先擱著, 有空再研究.