[筆記]如何使用C/C++編寫DLL或so供Python呼叫

maxresdefault - [筆記]如何使用C/C++編寫DLL或so供Python呼叫

最近在讀論文與到處Fork別人的專案的過程中,碰到了絕大部分使用Python,但為加速底層運算而使用C++來編寫函數的情況,在Windows 10 64位元的環境下讀取編譯好的so檔會出現「%1 不是正確的win32應用程式」,必須要自己在64位元的linux環境下重新編譯才能使用,在解決的過程中就順便記錄下來作為筆記。

假設今天我們分別使用C/C++寫了兩個簡單的函數求兩數總和:

//使用C編寫的test.c
__declspec(dllexport) int sum(int a, int b) {
    return a + b;
}
//使用C++編寫的test.cpp
#define DLLEXPORT extern "C" __declspec(dllexport)

DLLEXPORT int sum(int a, int b) {
    return a + b;
}

若你使用的是Windows,必須加上 __declspec(dllexport) 來讓裡面的函數是可被使用的,但如果你用的是 linux 的環境,則可以將它忽略。你也可以加入header檔,這個步驟加或不加都是可以的。

//test.h
int sum(int, int);

Windows 環境下,可以透過 Visual studio 建立 Dinamic-Link Library project,將程式碼納入後編譯即可。

mathlibrary desktop project wizard dll - [筆記]如何使用C/C++編寫DLL或so供Python呼叫

Linux環境下,可用gcc或g++來進行編譯,在終端機輸入

gcc -Wall -Wextra -O -ansi -pedantic -shared test.c -o test.so

若遇到「LD Link Failed – Bad Value」,吐出像下面這樣的錯誤,通常也是因為64位元的作業系統造成的;

/usr/bin/ld: /tmp/ccxJbKUI.o: relocation R_X86_64_PC32 against symbol `entityTotal' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status

可以輸入

g++ -std=c++11 -shared -fPIC -o test.so test.cpp

來解決這個問題。 得到了DLL/so檔之後,就可以在編寫Python的時候調用裡面的函數了,方法是這樣的:

from ctypes import cdll
mydll = cdll.LoadLibrary('test.dll')
mydll.sum(5, 3)
> 8