Der Zweck besteht darin, andere Programme in Python auszuführen. Insbesondere habe ich mich gefragt, ob ich das in C veröffentlichte SDK in Kombination mit Python verwenden könnte.
Ich habe dies übernommen, weil es möglich ist, andere ausführbare Programme von Python aus unter Verwendung des Unterprozesses des Python-Moduls auszuführen. Die Kommunikation mit anderen Prozessen umfasst eine prozessübergreifende Kommunikationsmethode namens PIPE, die sich anscheinend schnell erledigen lässt. Tatsächlich funktioniert es gut mit den folgenden Kombinationen von Python (Steuerung) und C (laufendes Programm).
OK.cpp
#include <stdio.h>
#define MAX_BUFFER 256
int main()
{
char buf[MAX_BUFFER];
fgets(buf, MAX_BUFFER, stdin);
printf("your input is :%s", buf);
return 0;
}
control.py
import subprocess as sp
if __name__ == "__main__":
#Starten Sie die exe-Datei als Prozess
#Verbinden Sie stdin und stdout als PIPE mit diesem Python
cmd = ".\\OK.exe"
p = sp.Popen(cmd, stdin=sp.PIPE, stdout=sp.PIPE)
#Senden Sie Anweisungen an eine Instanz von Popen mit kommunizieren
#Der Rückgabewert ist(stdout, stderr)Wegen des Taple von
#Weil b vor der Zeichenfolge in Byte konvertiert wird
out, err = p.communicate(input=b"Hello World")
print(out)
exit()
(Kompilieren Sie OK.cpp und legen Sie es als OK.exe im selben Ordner wie control.py unten ab.)
Das SDK, mit dem ich den geänderten Status durch die Eingabe von stdin behandeln wollte, erforderte jedoch viele Eingaben. In diesem Fall wird der Vorgang am Kommunikationsteil gestoppt, selbst wenn Sie dieselbe control.py wie zuvor verwenden. Ein solches C-Programm ist beispielsweise NG.
NG.cpp
#include <stdio.h>
#include <string.h>
#define MAX_BUFFER 256
int main()
{
char buf[MAX_BUFFER], *ret;
//Empfangen Sie weiter, bis die Eingabezeichenfolge ein Endzeichen enthält
while(1)
{
fgets(buf, MAX_BUFFER, stdin);
printf("your input is :%s", buf);
//Bestimmen Sie, ob die Eingabezeichenfolge ein Ende hat
ret = strstr(buf, "end");
//Wenn nicht, wird NULL in ret zurückgegeben, sodass die while-Anweisung beendet wird.
if(ret!=NULL)
{
break;
}
}
return 0;
}
Ich konnte auf der Python-Seite keine Implementierung finden, um dies zu lösen. Diesmal habe ich sie mit der Implementierung auf der C-Seite gelöst. Ein Beispiel für die Implementierung auf der C-Seite ist unten dargestellt. Wenn jedoch jemand weiß, wie dies auf der Python-Seite zu tun ist, würde ich es begrüßen, wenn Sie es mir sagen könnten. (Ich fand, dass pyexpect eine ziemlich gute Linie zu sein scheint, also habe ich es tatsächlich versucht, aber ich habe aufgegeben, weil ich nicht die volle Funktionalität nutzen konnte, es sei denn, es war Linux. Wenn ich es unter Linux mache, kann es etwas weniger problematisch sein. nicht)
Dieses Mal haben wir die TCP-Server / Client-Kommunikation übernommen, um Befehle zu empfangen und den Client-Prozess jedes Mal auf der Python-Seite zu starten. Ein Beispiel ist unten gezeigt.
main.cpp
#include "stdafx.h"
char *getCharTCP(char*);
int main()
{
char buf[DEFAULT_BUFLEN];
char *ret;
//Empfangen Sie weiter, bis die Eingabezeichenfolge ein Endzeichen enthält
while(1)
{
//fgets(buf, DEFAULT_BUFLEN, stdin);
printf("waiting new input :\n");
ret = getCharTCP(buf);
printf("your input is :%s", buf);
//Bestimmen Sie, ob die Eingabezeichenfolge ein Ende hat
ret = strstr(buf, "end");
//Wenn nicht, wird NULL in ret zurückgegeben, sodass die while-Anweisung beendet wird.
if(ret!=NULL)
{
break;
}
}
return 0;
}
getCharTCP.cpp
#include "stdafx.h"
char *getCharTCP(char *out)
{
WSADATA wsaData;
int iResult, i;
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET ClientSocket = INVALID_SOCKET;
struct addrinfo *result = NULL;
struct addrinfo hints;
int iSendResult;
char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;
char errorcode[DEFAULT_BUFLEN];
strcpy(errorcode, "error");
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return errorcode;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Resolve the server address and port
iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return errorcode;
}
// Create a SOCKET for connecting to server
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return errorcode;
}
// Setup the TCP listening socket
iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR) {
printf("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
return errorcode;
}
freeaddrinfo(result);
iResult = listen(ListenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR) {
printf("listen failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return errorcode;
}
// Accept a client socket
ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket == INVALID_SOCKET) {
printf("accept failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return errorcode;
}
// No longer need server socket
closesocket(ListenSocket);
// Receive until the peer shuts down the connection
do {
iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
if (iResult > 0) {
printf("Bytes received: %d\n", iResult);
// Echo the buffer back to the sender
iSendResult = send(ClientSocket, recvbuf, iResult, 0);
if (iSendResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return errorcode;
}
printf("Bytes sent: %d\n", iSendResult);
}
else if (iResult == 0)
printf("Connection closing...\n");
else {
printf("recv failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return errorcode;
}
} while (iResult > 0);
// shutdown the connection since we're done
iResult = shutdown(ClientSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return errorcode;
}
// cleanup
closesocket(ClientSocket);
WSACleanup();
for (i = strlen(recvbuf) - 1; i >= 0; i--)
{
strncpy(out, recvbuf, i + 1);
out[i + 1] = '\0';
break;
}
printf("receive end\n");
return out;
}
stdafx.cpp
#include "stdafx.h"
stdafx.h
#pragma once
//Deaktivieren Sie Visual Studio-Warnungen
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
//include für getCharTCP
#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
// Need to link with Ws2_32.lib
#pragma comment (lib, "Ws2_32.lib")
// #pragma comment (lib, "Mswsock.lib")
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "27015"
main.cpp
#include "stdafx.h"
int main(int argc, char **argv)
{
WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
char sendbuf[DEFAULT_BUFLEN];
char recvbuf[DEFAULT_BUFLEN];
int iResult;
int recvbuflen = DEFAULT_BUFLEN;
printf("please write letters to control program :\n");
fgets(sendbuf, DEFAULT_BUFLEN, stdin);
// Validate the parameters
if (argc != 2) {
printf("usage: %s server-name\n", argv[0]);
return 1;
}
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// Resolve the server address and port
iResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
// Attempt to connect to an address until one succeeds
for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {
// Create a SOCKET for connecting to server
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
// Connect to server.
iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
continue;
}
break;
}
freeaddrinfo(result);
if (ConnectSocket == INVALID_SOCKET) {
printf("Unable to connect to server!\n");
WSACleanup();
return 1;
}
// Send an initial buffer
iResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0);
if (iResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
printf("Bytes Sent: %ld\n", iResult);
// shutdown the connection since no more data will be sent
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
// Receive until the peer closes the connection
do {
iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
if (iResult > 0)
printf("Bytes received: %d\n", iResult);
else if (iResult == 0)
printf("Connection closed\n");
else
printf("recv failed with error: %d\n", WSAGetLastError());
} while (iResult > 0);
// cleanup
closesocket(ConnectSocket);
WSACleanup();
return 0;
}
stdafx.h
#pragma once
#include <stdio.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "27015"
(Ich habe das kompilierte Serverprogramm und das Clientprogramm im selben Ordner wie Python abgelegt.)
control.py
import subprocess as sp
if __name__ == "__main__":
#Starten Sie die exe-Datei auf der Serverseite
#Diese Datei ist das SDK
cmd = ".\\server.exe"
pserve = sp.Popen(cmd)
#Clientseitiges Programm
cmd = ".\\client.exe localhost"
pclient = sp.Popen(cmd, stdin=sp.PIPE, stdout=sp.PIPE)
out, err = pclient.communicate(input=b"Hello World 1st\n")
pclient.kill()
#Sie müssen jedes Mal eine Instanz starten, wenn Sie einen Befehl senden
#Ich denke, es gibt eine bessere Umsetzung
cmd = ".\\client.exe localhost"
pclient = sp.Popen(cmd, stdin=sp.PIPE, stdout=sp.PIPE)
out, err = pclient.communicate(input=b"Hello World 2nd\n")
pclient.kill()
exit()
Ich fing an zu denken, dass das Python-Modul sofort damit umgehen kann, aber ich war unerwartet süchtig danach, also schrieb ich es auf. Ich bin der Meinung, dass es eine bessere Lösung gibt (z. B. die Kommunikation zwischen Prozessen mit PIPE), sodass ich möglicherweise die Gelegenheit nutzen kann, weitere Untersuchungen durchzuführen. Da wir jedoch die TCP-Kommunikation implementiert haben, war es meiner Meinung nach ein guter Teil, dass sie von anderen PCs als Nebenprodukt ausgeführt werden konnte. Möglicherweise gibt es eine andere gute Steuerungsmethode, die das Python-Socket-Modul verwendet.
OS:Win10 IDE: Visual Studio 2017 (sowohl C als auch Python wurden in VS2017 erstellt) Python : Anaconda 5.0.1
Python-Beamter: Unterprozess [Achtung], wenn Sie eine Zeichenfolge in einer Funktion zurückgeben möchten (https://fa11enprince.hatenablog.com/entry/2014/06/10/023712) Beispiel für die Implementierung von Winsock2 (TCP-Kommunikation): Erste Schritte mit Winsock2
Recommended Posts