0
以下代碼是較大軟件包的片段。我想了解代碼如何管理像numpy數組,單元格這樣的對象。我想知道的是,代碼似乎沒有序列化對象,但它確實有效。它爲什麼有效?通過Python中的套接字發送對象到C/Fortran
Python客戶機代碼(片斷):
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)
用C接收代碼(片斷):
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)
而這個接收代碼確實得到了一個二維數組,等等。同樣的作品在相反的方向。
謝謝您的回答。你的意思是你預計鴨子打字會不會起作用?另外,我編寫了一個小的示例python代碼,其中接收者和發件人是一個python套接字,併發送了一些numpy數組。它的工作,但收到的數據沒有恢復,我得到▯▯作爲收到的數據的價值。 – Jadzia
@Jadzia我希望鴨子打字工作。至於你的示例代碼,我認爲如果你感興趣,最好發表另一個問題。可能並非所有numpy的內容都可以通過網絡「按原樣」發送。也有可能發送接收中存在不正確的內容,但我不敢堅持,因爲我沒有看到代碼。 – Vovanrock2002
send/sendall需要一個實現緩衝協議API的「類字節」對象。目前緩衝協議只能在C中實現。這就是爲什麼你可以發送像'array.array'和'numpy.array'和'memoryview'這樣的東西,它不能從'bytes'繼承,但是要實現C API。有一個公開票證允許緩衝協議的純Python實現,但它是低優先級的(已經開放了近5年)。 https://bugs.python.org/issue13797 – Dunes