利用 Tiny C compiler 編譯 Windows 10 64 位元 dll 動態連結庫, 並由 Python 程式呼叫執行.
利用 Tiny C 編譯 Tiny C
從 http://download.savannah.gnu.org/releases/tinycc/ 下載 Win64 C 程式編譯器, 並下載 Tiny C compiler 0.9.26 版程式原始碼. 利用下列批次檔案進行編譯.
compileTCC.bat 檔案內容:
echo Use TCC to compile TCC echo Set CC=tcc set CC=tcc set target=-DTCC_TARGET_PE -DTCC_TARGET_X86_64 set P=64 echo tools: tiny_impdef.exe, tiny_libmaker.exe %CC% %target% win32/tools/tiny_impdef.c -o tiny_impdef.exe %CC% %target% win32/tools/tiny_libmaker.c -o tiny_libmaker.exe echo Compile libtcc.dll if not exist libtcc\nul mkdir libtcc %CC% %target% -w -shared -DLIBTCC_AS_DLL -DONE_SOURCE libtcc.c -o libtcc.dll tiny_impdef libtcc.dll -o libtcc/libtcc.def echo Compile tc.exe %CC% %target% tcc.c -o tc.exe -ltcc -Llibtcc echo Compile libcc1.a %CC% %target% -c lib/libtcc1.c %CC% %target% -c win32/lib/crt1.c %CC% %target% -c win32/lib/wincrt1.c %CC% %target% -c win32/lib/dllcrt1.c %CC% %target% -c win32/lib/dllmain.c %CC% %target% -c win32/lib/chkstk.S %CC% %target% -c lib/alloca86_64.S tiny_libmaker lib/libtcc1.a libtcc1.o alloca86_64.o crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o
編譯 dll 動態程式庫
首先, 建立一個 multiply.c 程式:
#include <stdio.h> int multiply(int, int); __declspec(dllexport) int multiply(int num1, int num2) { return num1 * num2; }
利用下列指令, 將 multiply.c 編譯為動態連結庫 myltiply.dll
tcc -w -shared -DLIBTCC_AS_DLL -DONE_SOURCE multiply.c -o multiply.dll
接著利用下列 Python3 程式, 透過 ctypes 模組導入 multiply.dll, 並且執行動態連結程式庫中的 multiply() 函式.
import ctypes lib = ctypes.CDLL('multiply.dll') result = lib.multiply(3, 2) print(result)
因為 ctypes 內建傳回值為 int, 因此若 C 對應動態連結庫輸入或傳回值為浮點數, 就必須手動宣告.
例如, 將上述函式的輸入與輸出均由 int 改為 float 如下:
// multiply2.c #includefloat multiply(float, float); __declspec(dllexport) float multiply(float num1, float num2) { return num1 * num2; }
可利用下列指令, 將 multiply2.c 編譯為動態連結庫 myltiply2.dll
tcc -w -shared -DLIBTCC_AS_DLL -DONE_SOURCE multiply2.c -o multiply2.dll
但是 Python3 程式部份就必須改為:
import ctypes lib = ctypes.CDLL('multiply2.dll') # By default functions are assumed to return the C int type. Other return types can be specified by setting the restype attribute of the function object. lib.multiply.restype = ctypes.c_float result = lib.multiply(ctypes.c_float(3.0), ctypes.c_float(2.0)) print(result)