1. 程式人生 > >實現C#和Python高效率混合程式設計

實現C#和Python高效率混合程式設計

為什麼C#和Python要屢屢進行混合程式設計呢?之前我們提到了使用託管C++封裝Python的核心庫為一個託管dll,然後供C#呼叫的途徑,這種方式算是一種比較科學的方式。但是它仍然有兩個小的問題,一來,我們是封裝了Win平臺的Python,使用的是託管C++,這就側面說明了這個託管dll是服從於.NET Framework的,而.NET Framework和Windows繫結。二來,我們如果通過原始碼的形式來呼叫Python,那麼Python簡易方便的編碼特性就會完全丟失。總結下來就是兩個缺點

1.無法跨平臺

2.無法進行優雅的程式設計

3.進行型別轉換的時候比較麻煩

麼提到混合程式設計,還是有非常多的方式的,這裡的話,我們實現一種最基本的方式,案例就採用C#和Python。

這種方式就是通過一種傳輸渠道,可以是檔案,也可以是任何的通訊渠道。(不管什麼渠道,它們都有一個特性,即它們的規範和實現它們的語言沒有任何關係)。此處我就可以通過socket來實現,如果是socket實現,那麼很好的解決了跨平臺和簡易程式設計的問題(此處的簡易程式設計指的是,如果我們通過封裝原始碼的形式來呼叫,則完全拋棄了語言的語法)

socket適用於很多不同的語言之間,現在我們嘗試用C#和Python來進行普通的交流

預設C#是服務端而Python是客戶端

class PyTransfer {
    //和Python語言進行socket通訊
    //communicate with Python by socket

    Socket server; //伺服器套接字
    Socket client; //使用者套接字

    IPAddress ip;
    int port;           //服務端ip和埠號
}

先宣告出我們需要的內容,隨後我們需要知道乙太網的ip地址,也就是本地伺服器的ip地址

        public static string GetHostIP()
        {
            string ret = "";
            IPAddress[] ips = Dns.GetHostEntry(Dns.GetHostName()).AddressList;
            foreach (IPAddress ip in ips)
            {
                if (ip.AddressFamily == AddressFamily.InterNetwork)
                {
                    ret = ip.MapToIPv4().ToString();
                }
            }
            if (ret == "")
            {
                return null;
            }
            return ret;
        }

寫了一個比較簡單的函式去實現,更多的內容可以參考計算機網路

然後是構造器當中的內容

class PyTransfer {
        //和Python語言進行socket通訊
        //communicate with Python by socket

        Socket server; //伺服器套接字
        Socket client; //使用者套接字

        IPAddress ip;
        int port;           //服務端ip和埠號

        public PyTransfer(string address,int port) {
            server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            ip = IPAddress.Parse(address);
            this.port = port;
            server.Bind(new IPEndPoint(ip,port));
        }
        public static string GetHostIP()
        {
            string ret = "";
            IPAddress[] ips = Dns.GetHostEntry(Dns.GetHostName()).AddressList;
            foreach (IPAddress ip in ips)
            {
                if (ip.AddressFamily == AddressFamily.InterNetwork)
                {
                    ret = ip.MapToIPv4().ToString();
                }
            }
            if (ret == "")
            {
                return null;
            }
            return ret;
        }
}

最後,我們開始伺服器的監聽。

        public void StartRun() {
            this.server.Listen(1);      //開始監聽
            while (true) {
                Console.WriteLine("wait for client to connect...");
                client = this.server.Accept();
                break;
            }
            while (true) {
                Console.Write("enter your message>>>");
                string message = Console.ReadLine();
                client.Send(System.Text.Encoding.Default.GetBytes(message.ToString()));
            }
        }

這樣,一套完整的伺服器就構建好了,雖然內容不是非常的完善,但是足夠提供我們能力去和Python交流了。

現在我們在主函式中把它例項化。

最後,我們再實現Python客戶端的程式碼即可。

import socket


ip = socket.gethostbyname(socket.gethostname())
port = 45535

server_address_family = (ip,port)       #伺服器地址族

try:
    client = socket.socket()
    client.connect(server_address_family)
    print("python has already connect to C#")
    print("wait message from C#")
    while 1:
        msg = client.recv(1024)
        print(msg.decode())
except Exception as e :
    print(e)
    print("連線失敗...")

完成之後,兩者執行的效果可以在下圖中看到。實現交流之後,我們就可以定義自己的協議,來規定什麼時候傳輸資料,什麼時候傳輸程式碼,什麼時候傳輸檔案等。如果不懂的問題,可以加我qq529324416,也可以加我的技術討論群493486382