Le but est d'exécuter d'autres programmes en Python. Plus précisément, je me demandais si je pourrais utiliser le SDK publié en langage C en combinaison avec Python.
J'ai adopté cela car il est possible d'exécuter d'autres programmes exécutables à partir de Python en utilisant le sous-processus du module Python. La communication avec d'autres processus comprend une méthode de communication inter-processus appelée PIPE, et il semble que cela puisse être fait rapidement. En fait, cela fonctionne bien avec les combinaisons suivantes de Python (contrôle) et C (programme en cours d'exécution).
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__":
#Lancez le fichier exe en tant que processus
#Connectez stdin et stdout en tant que PIPE à ce Python
cmd = ".\\OK.exe"
p = sp.Popen(cmd, stdin=sp.PIPE, stdout=sp.PIPE)
#Envoyer des instructions à une instance de Popen avec Communiquer
#La valeur de retour est(stdout, stderr)À cause du tapage de
#Parce que b avant que la chaîne de caractères soit convertie en octet
out, err = p.communicate(input=b"Hello World")
print(out)
exit()
(Compilez OK.cpp et placez-le comme OK.exe dans le même dossier que control.py ci-dessous)
Cependant, le SDK que je voulais gérer a changé d'état via l'entrée de stdin et a nécessité une entrée plusieurs fois. Dans ce cas, même si vous utilisez le même control.py qu'avant, l'opération s'arrêtera au niveau de la partie de communication. Par exemple, un tel programme C est NG.
NG.cpp
#include <stdio.h>
#include <string.h>
#define MAX_BUFFER 256
int main()
{
char buf[MAX_BUFFER], *ret;
//Continuer à recevoir des entrées jusqu'à ce qu'il y ait un caractère de fin dans la chaîne de caractères d'entrée
while(1)
{
fgets(buf, MAX_BUFFER, stdin);
printf("your input is :%s", buf);
//Déterminez si la chaîne d'entrée a une fin
ret = strstr(buf, "end");
//Sinon, NULL est retourné dans ret, donc l'instruction while est quittée.
if(ret!=NULL)
{
break;
}
}
return 0;
}
Je n'ai pas trouvé d'implémentation côté Python pour résoudre cela ... donc cette fois je l'ai résolu avec l'implémentation côté C. Un exemple d'implémentation du côté C est montré ci-dessous, mais si quelqu'un sait comment faire cela du côté Python, j'apprécierais que vous me le disiez. (J'ai trouvé que pyexpect est une très bonne ligne, donc je l'ai essayé, mais j'ai abandonné parce que je ne pouvais pas utiliser toutes les fonctionnalités à moins que ce ne soit Linux. Si je le fais sous Linux, c'est peut-être un peu moins difficile. ne pas)
Cette fois, nous avons adopté la communication serveur / client TCP pour recevoir des commandes et démarrer le processus client côté Python à chaque fois. Un exemple est présenté ci-dessous.
main.cpp
#include "stdafx.h"
char *getCharTCP(char*);
int main()
{
char buf[DEFAULT_BUFLEN];
char *ret;
//Continuer à recevoir des entrées jusqu'à ce qu'il y ait un caractère de fin dans la chaîne de caractères d'entrée
while(1)
{
//fgets(buf, DEFAULT_BUFLEN, stdin);
printf("waiting new input :\n");
ret = getCharTCP(buf);
printf("your input is :%s", buf);
//Déterminez si la chaîne d'entrée a une fin
ret = strstr(buf, "end");
//Sinon, NULL est retourné dans ret, donc l'instruction while est quittée.
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
//Désactiver les avertissements Visual Studio
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
//inclure pour 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"
(J'ai mis le programme serveur compilé et le programme client dans le même dossier que Python)
control.py
import subprocess as sp
if __name__ == "__main__":
#Lancez le fichier exe côté serveur
#Ce fichier est le SDK
cmd = ".\\server.exe"
pserve = sp.Popen(cmd)
#Programme côté client
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()
#Vous devez lancer une instance à chaque fois que vous envoyez une commande
#Je pense qu'il y a une meilleure mise en œuvre
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()
J'ai commencé à penser que le module Python serait capable de le gérer immédiatement, mais j'en étais accro de manière inattendue, alors je l'ai écrit. Je pense qu'il existe une meilleure solution (telle que la communication inter-processus avec PIPE), alors je peux profiter de l'occasion pour enquêter davantage. Cependant, depuis que nous avons implémenté la communication TCP, je pense que c'était une bonne partie qu'elle puisse être exécutée à partir d'autres PC en tant que sous-produit. Il peut y avoir une autre bonne méthode de contrôle utilisant le module socket de Python.
OS:Win10 IDE: Visual Studio 2017 (C et Python ont été créés dans VS2017) Python : Anaconda 5.0.1
Officiel Python: sous-processus [Attention] lorsque vous souhaitez renvoyer une chaîne de caractères dans une fonction (https://fa11enprince.hatenablog.com/entry/2014/06/10/023712) Exemple d'implémentation Winsock2 (communication TCP): Premiers pas avec Winsock2
Recommended Posts