Мне удалось получить C-код, который с радостью вызывает скрипты Python в Unix, используя PIPES в C-коде.Теперь мне нужно сделать то же самое в Windows.
По сути, я хотел бы написать сценарии на разных языках сценариев, таких как Python / Lua и т. Д. В Windows, и иметь возможность выполнять их с использованием STDIN / STDOUT и т. Д.
Я смотрел на вызов «CreateProcess» по адресу:
http://msdn.microsoft.com/en-us/library/ms682425(VS.85).aspx
и хотя я могу заставить его работать с «потомком, написанным на C», я не могу его получитьдля вызова скрипта Python.
Ниже "код родителя / отправителя" на моем окне Windows:
#include<windows.h>
#include <stdio.h>
#include <stdlib.h>
#pragma comment(lib, "User32.lib")
void DisplayError(char *pszAPI);
void readFromPipe(HANDLE hPipeRead);
void createChildProcess(char *commandLine,
HANDLE hChildStdOut,
HANDLE hChildStdIn,
HANDLE hChildStdErr);
DWORD WINAPI writeToPipe(LPVOID lpvThreadParam);
HANDLE hChildProcess = NULL;
HANDLE hStdIn = NULL;
BOOL bRunThread = TRUE;
char *inputStream;
int main(int argc, char *argv[]){
HANDLE hOutputReadTmp,hOutputRead,hOutputWrite;
HANDLE hInputWriteTmp,hInputRead,hInputWrite;
HANDLE hErrorWrite;
HANDLE hThread;
DWORD ThreadId;
SECURITY_ATTRIBUTES sa;
int streamLen;
sa.nLength= sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
if (!CreatePipe(&hOutputReadTmp,&hOutputWrite,&sa,0))
return 1;
if (!DuplicateHandle(GetCurrentProcess(),hOutputWrite,
GetCurrentProcess(),&hErrorWrite,0,
TRUE,DUPLICATE_SAME_ACCESS))
return 1;
if (!CreatePipe(&hInputRead,&hInputWriteTmp,&sa,0))
return 1;
if (!DuplicateHandle(GetCurrentProcess(),hOutputReadTmp,
GetCurrentProcess(),
&hOutputRead,
0,FALSE,
DUPLICATE_SAME_ACCESS))
return 1;
if (!DuplicateHandle(GetCurrentProcess(),hInputWriteTmp,
GetCurrentProcess(),
&hInputWrite,
0,FALSE,
DUPLICATE_SAME_ACCESS))
return 1;
if (!CloseHandle(hOutputReadTmp)) return 1;;
if (!CloseHandle(hInputWriteTmp)) return 1;;
if ( (hStdIn = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE )
return 1;
if (argc == 2){
createChildProcess(argv[1], hOutputWrite,hInputRead,hErrorWrite);
}else{
puts("No process name / input stream specified\n");
return 1;
}
if (!CloseHandle(hOutputWrite)) return 1;;
if (!CloseHandle(hInputRead )) return 1;;
if (!CloseHandle(hErrorWrite)) return 1;;
hThread = CreateThread(NULL,0,writeToPipe,
(LPVOID)hInputWrite,0,&ThreadId);
if (hThread == NULL)
return 1;;
readFromPipe(hOutputRead);
if (!CloseHandle(hStdIn))
return 1;
bRunThread = FALSE;
if (WaitForSingleObject(hThread,INFINITE) == WAIT_FAILED)
return 1;;
if (!CloseHandle(hOutputRead)) return 1;;
if (!CloseHandle(hInputWrite)) return 1;;
}
void createChildProcess(char *commandLine,
HANDLE hChildStdOut,
HANDLE hChildStdIn,
HANDLE hChildStdErr){
PROCESS_INFORMATION pi;
STARTUPINFO si;
ZeroMemory(&si,sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdOutput = hChildStdOut;
si.hStdInput = hChildStdIn;
si.hStdError = hChildStdErr;
if (!CreateProcess(NULL,commandLine,NULL,NULL,TRUE,
NULL,NULL,NULL,&si,&pi))
hChildProcess = pi.hProcess;
if (!CloseHandle(pi.hThread)) return 1;;
}
void readFromPipe(HANDLE hPipeRead)
{
CHAR lpBuffer[256];
DWORD nBytesRead;
DWORD nCharsWritten;
while(TRUE)
{
if (!ReadFile(hPipeRead,lpBuffer,sizeof(lpBuffer),
&nBytesRead,NULL) || !nBytesRead)
{
if (GetLastError() == ERROR_BROKEN_PIPE)
break; // pipe done - normal exit path.
else
return 1; // Something bad happened.
}
if (!WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),lpBuffer,
nBytesRead,&nCharsWritten,NULL))
return 1;;
}
}
DWORD WINAPI writeToPipe(LPVOID lpvThreadParam)
{
CHAR read_buff[256];
DWORD nBytesRead,nBytesWrote;
HANDLE hPipeWrite = (HANDLE)lpvThreadParam;
while (bRunThread){
nBytesRead = 21;
strncpy(read_buff, "hello from the paren\n",21);
read_buff[nBytesRead] = '\0';
if (!WriteFile(hPipeWrite,read_buff,nBytesRead,&nBytesWrote,NULL)){
if (GetLastError() == ERROR_NO_DATA)
break; //Pipe was closed (normal exit path).
else
return 1;;
}
}
return 1;
}
Немного из приведенного выше кода "жестко закодировано" только для целей тестирования... по сути, я передаю какой-то текст типа "привет от парня" для отправки в "child.exe" ....
Вот код для child.c ... простого ECHOиз того, что отправлено на него
#include<windows.h>
#include<stdio.h>
#include<string.h>
void main (){
CHAR szInput[1024];
ZeroMemory(szInput,1024);
gets(szInput);
puts(szInput);
fflush(NULL);
}
Для запуска приложения я отправляю "CallSubProcess.exe Child.exe", и он работает 100%
Далее я хочу изменить "child.c"быть PYTHON SCRIPT ...
import sys
if __name__ == "__main__":
inStream = sys.stdin.read()
outStream = inStream
sys.stdout.write(outStream)
sys.stdout.flush()
Так как я могу изменить вызов CreateProcess для выполнения этого скрипта?
if (!CreateProcess("C:\\Python26\\python.exe", "echo.py",NULL, NULL,FALSE, 0,NULL,NULL,&si,&pi)){
Но это никогда не работает.
Есть идеи, как мне заставить это работать?Любая помощь будет принята с благодарностью.