使用Python調用動態庫

我我的在平常使用電腦時,常常須要使用Google,因而就要切換代理,基本上是一下子切換爲代理,一下子切換成直連,總是打開internet 選項去設置,很不方便,因而我萌生了一個想法:python

作一個開關,我想用代理的時候,就點一下打開。不想用時,就再點一下關閉。c++

簡單的說,就是自動更改IE的代理設置。git

實際上這個功能可使用純python實現,其核心的原理就是使用 Windows API InternetSetOption。可是python去調用這個api至關複雜,不過人家已經實現過了,參見stackoverflow的問題github

不過話說回來,想調用windows api這件事,爲何不適用c/c++來實現呢,這對他們來講很簡單就實現了,繞python一圈感受不是很合理。windows

因此,這一段用c++來寫,而後其餘地方要調用直接調用就行了,使用c++來更改代理服務器,代碼大概長這個樣子:api

IEPROXY_API bool setproxy(TCHAR* server, bool enabled)
{
    INTERNET_PER_CONN_OPTION_LIST list;
    DWORD dwBufSize = sizeof(list);

    // Fill the list structure.
    list.dwSize = sizeof(list);

    // NULL == LAN, otherwise connectoid name.
    list.pszConnection = nullptr;

    // Set three options.
    list.dwOptionCount = 3;
    list.pOptions = new INTERNET_PER_CONN_OPTION[3];

    // Ensure that the memory was allocated.
    if (nullptr == list.pOptions)
    {
        // Return FALSE if the memory wasn't allocated.
        return false;
    }

    // Set flags.
    list.pOptions[0].dwOption = INTERNET_PER_CONN_FLAGS;
    list.pOptions[0].Value.dwValue = enabled ? PROXY_TYPE_PROXY : PROXY_TYPE_DIRECT;

    // Set proxy name.
    list.pOptions[1].dwOption = INTERNET_PER_CONN_PROXY_SERVER;

    list.pOptions[1].Value.pszValue = server;

    // Set proxy override.
    list.pOptions[2].dwOption = INTERNET_PER_CONN_PROXY_BYPASS;
    list.pOptions[2].Value.pszValue = TEXT("localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;172.32.*;192.168.*");

    // Set the options on the connection.
    auto bReturn = InternetSetOption(nullptr,
                                     INTERNET_OPTION_PER_CONNECTION_OPTION, &list, dwBufSize);
    if (bReturn)
    {
        InternetSetOption(nullptr,
                          INTERNET_OPTION_SETTINGS_CHANGED, nullptr, 0);
        InternetSetOption(nullptr,
                          INTERNET_OPTION_REFRESH, nullptr, 0);
    }

    // Free the allocated memory.
    delete[] list.pOptions;
    return bReturn;
}

看起來代碼有點長,其實有用的就那麼兩三行而已。服務器

總之,c++部分的代碼作好,編譯,最後生成一個dll,用dependency walker打開,裏面能看到有三個c函數。ide

dll內的函數
下一步纔是今天的主題,若是用python再調用。函數

使用python調用

嘗試一下用ctypes來實現,ctypes提供跟c兼容的數據類型,也容許你調用DLL,你能夠用ctypes來封裝純python的api。命令行

它使用起來也特別簡單,基本上就只有三句話:

  1. from ctypes import *
  2. lib = cdll.LoadLibrary(dll_path)
  3. lib.setproxy(args.proxy, true)

首先引入ctypes,這沒必要說了。而後使用cdll.LoadLibrary再裝載dll,最後調用dll內部的函數,setproxy就是我以前寫的c的函數,上面的圖上有。整個過程很天然,很簡單。

我最早嘗試的是用pyqt來作一個圖形的界面,每次都在這個圖形界面上打開和關閉代理,但後來以爲這也太複雜了,圖形化的反而不如命令行簡單直接,那不如直接寫成命令行的算了,雙擊腳本a就打開,雙擊b就關閉,而後把a和b都放在桌面上就行了嘛。

因而乎,就有了下面的兩個bat文件:

disable-proxy.bat

python.exe .\setproxy.py --proxy 127.0.0.1:8118 --switch 0

enabled-proxy.bat

python.exe .\setproxy.py --proxy 127.0.0.1:8118 --switch 1

我把這兩個bat文件的快捷方式放在桌面上,用的時候雙擊其中一個就行。

固然了,你都用c寫成了一個dll了,那乾脆你也寫成一個獨立的exe算了,exe內部解析命令行。
是的,這樣更好了,都不須要python的環境了,不過,下次再寫吧。

本文涉及到的源代碼在 Github-Syler-Fun

本文地址:https://1few.com/python-ctypes-call-c/

相關文章
相關標籤/搜索