2016-11-21 17 views
0

次のコードは、より大きなソフトウェアパッケージのスニペットです。コードがどのようにnumpy配列、セルなどのオブジェクトを送信するかを管理したいと考えています。私が疑問に思うのは、コードがオブジェクトを直列化しているようには見えないが、動作するということです。それはなぜ機能するのですか?PythonからC/Fortranへのソケット経由のオブジェクトの送信

Pythonクライアントコード(スニペット):Cでコードを受信

class DriverSocket(socket.socket): 

    def __init__(self, _socket_interface): 
     super(DriverSocket,self).__init__(_sock=_socket_interface) 


    def sendpos(self, pos, cell): 
     """Sends the position and cell data to the driver. 

     Args: 
     pos: An array containing the atom positions. 
     cell: A cell object giving the system box. 

     Raises: 
     InvalidStatus: Raised if the status is not Ready. 
     """ 

     if (self.status & Status.Ready): 
     try: 
      self.sendall(Message("posdata")) 
      self.sendall(cell.h) 
      self.sendall(cell.ih) 
      self.sendall(np.int32(len(pos)/3)) 
      self.sendall(pos) 
     except: 
      self.poll() 
      return 
     else: 
     raise InvalidStatus("Status in sendpos was " + self.status) 

(スニペット):

void open_socket_(int *psockfd, int* inet, int* port, char* host) 
/* Opens a socket. 

Note that fortran passes an extra argument for the string length, but this is 
ignored here for C compatibility. 

Args: 
    psockfd: The id of the socket that will be created. 
    inet: An integer that determines whether the socket will be an inet or unix 
     domain socket. Gives unix if 0, inet otherwise. 
    port: The port number for the socket to be created. Low numbers are often 
     reserved for important channels, so use of numbers of 4 or more digits is 
     recommended. 
    host: The name of the host server. 
*/ 

{ 
    int sockfd, portno, n; 
    struct hostent *server; 

    struct sockaddr * psock; int ssock; 

    if (*inet>0) 
    { // creates an internet socket 
     struct sockaddr_in serv_addr;  psock=(struct sockaddr *)&serv_addr;  ssock=sizeof(serv_addr); 
     sockfd = socket(AF_INET, SOCK_STREAM, 0); 
     if (sockfd < 0) error("Error opening socket"); 

     server = gethostbyname(host); 
     if (server == NULL) 
     { 
     fprintf(stderr, "Error opening socket: no such host %s \n", host); 
     exit(-1); 
     } 

     bzero((char *) &serv_addr, sizeof(serv_addr)); 
     serv_addr.sin_family = AF_INET; 
     bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length); 
     serv_addr.sin_port = htons(*port); 
     if (connect(sockfd, psock, ssock) < 0) error("Error opening socket: wrong host address, or broken connection"); 
    } 
    else ... 



void readbuffer_(int *psockfd, char *data, int* plen) 
/* Reads from a socket. 

Args: 
    psockfd: The id of the socket that will be read from. 
    data: The storage array for data read from the socket. 
    plen: The length of the data in bytes. 
*/ 

{ 
    int n, nr; 
    int sockfd=*psockfd; 
    int len=*plen; 

    n = nr = read(sockfd,data,len); 

    while (nr>0 && n<len) 
    { nr=read(sockfd,&data[n],len-n); n+=nr; } 

    if (n == 0) error("Error reading from socket: server has quit or connection broke"); 
} 

そしてC-ソケットコードを使用するFortranコードがある

CALL open_socket(socket, inet, port, host) 
... 
CALL readbuffer(socket, msgbuffer, nat*3*8) 

この受信コードは、実際には2次元配列などを取得します。同じことが逆の方向に働く。

答えて

0

send/sendallで任意のオブジェクトを送信しようとすると、バイトのように見える例外が表示されます。したがって、アイデアはシンプルで、numpyの構造はバイトのようなインターフェイスを提供し、バイトへの変換は生のバイナリデータだけを残します。

最も簡単な実装がbytesを継承することである。

class A: pass 
sock.sendall(A()) # exception 

class B(bytes): pass 
sock.sendall(B()) # no exception 

しかし、numpyのは、それらは同様の機能を提供するためにC APIを使用することができるパイソン、CythonとCで書かれた複雑なフレームワークです。

また、私が期待するようダックタイピングはここで働いていないことは注目に値します:あなたの答えのための

class C: 
    def __bytes__(self): 
     return bytes() 

sock.sendall(C()) # exception 
+0

感謝を。あなたは、アヒルのタイピングがうまくいくと思いますか?また、私は小さなサンプルのPythonコードをプログラミングしました。ここで、受信者と送信者はPythonソケットであり、いくつかのnumpy配列を送りました。それは働いたが、受け取ったデータは回復されなかった、私は受け取ったデータの価値としてgotを得た。 – Jadzia

+0

@Jadzia私はダックタイピングが働くことを期待していました。あなたのサンプルコードについては、興味があれば別の質問を投稿する方が良いと思います。 numpyのすべてが "そのまま"ネットワークを介して送信できるわけではない可能性があります。あなたのセンド受信に間違ったことがあるかもしれませんが、私はコードを見ないのでこれを主張するつもりはありません。 – Vovanrock2002

+0

send/sendallは、バッファプロトコルAPIを実装している「バイト様」オブジェクトを想定しています。現在のところ、バッファプロトコルはCでしか実装できません。これは 'array.array'や' numpy.array'や 'memoryview'のようなものを' bytes'から継承しないで送ることができますが、C APIを実装する理由です。純粋なpythonのバッファプロトコルの実装を可能にするオープンチケットがありますが、それは低い優先順位です(ほぼ5年間開かれています)。 https://bugs.python.org/issue13797 – Dunes

関連する問題