为什么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

更多推荐

实现C#和Python高效率混合编程