我想知道如何從我的C代碼使用execl
(或類似)來執行Python(或Lua等)腳本?如何使用EXECL從C代碼執行Python腳本?
下面是一些「父母/孩子」代碼,顯示了我如何使用PIPES向孩子發送數據流。代碼可能不完美,但你明白了。注意execl
底部:
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define STDIN_FILENO 0 /* Standard input. */
#define STDOUT_FILENO 1 /* Standard output. */
#define STDERR_FILENO 2 /* Standard error output. */
#define MAXLINE 4096
int main(void){
int n, parent_child_pipe[2], child_parent_pipe[2];
pid_t pid;
char line[MAXLINE];
if (pipe(parent_child_pipe) < 0 || pipe(child_parent_pipe) < 0)
puts("Error creating pipes...\n");
if ((pid = fork()) < 0)
puts("Error forking...\n");
else if (pid > 0) { /* PARENT */
close(parent_child_pipe[0]);
close(child_parent_pipe[1]);
while (fgets(line, MAXLINE, stdin) != NULL) {
n = strlen(line);
if (write(parent_child_pipe[1], line, n) != n)
puts("write error to pipe...\n");
if ((n = read(child_parent_pipe[0], line, MAXLINE)) < 0)
puts("read error from pipe...\n");
if (n == 0) {
puts("child closed pipe...\n");
break;
}
line[n] = 0; /* null terminate */
if (fputs(line, stdout) == EOF)
puts("fputs error...\n");
}
if (ferror(stdin))
puts("fgets error on stdin...\n");
exit(0);
} else { /* CHILD */
close(parent_child_pipe[1]);
close(child_parent_pipe[0]);
if (parent_child_pipe[0] != STDIN_FILENO) {
if (dup2(parent_child_pipe[0], STDIN_FILENO) != STDIN_FILENO)
puts("dup2 error to stdin...\n");
close(parent_child_pipe[0]);
}
if (child_parent_pipe[1] != STDOUT_FILENO) {
if (dup2(child_parent_pipe[1], STDOUT_FILENO) != STDOUT_FILENO)
puts("dup2 error to stdout...\n");
close(child_parent_pipe[1]);
}
**if (execl("./child", "child", (char *) 0) < 0)**
puts("execl error...\n");
}
}
現在的「孩子」的計劃上面寫的C和只需通過STDIN接收流,操縱流,並將其發回了使用標準輸出。
喜歡的東西:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define STDIN_FILENO 0 /* Standard input. */
#define STDOUT_FILENO 1 /* Standard output. */
#define STDERR_FILENO 2 /* Standard error output. */
#define MAXLINE 4096
int main(void){
int n;
char line[MAXLINE];
while ((n = read(STDIN_FILENO, line, MAXLINE)) > 0) {
line[n] = 0; /* null terminate */
n = strlen(line);
if (write(STDOUT_FILENO, line, n) != n)
puts("write error");
}
exit(0);
}
所以這是工作的罰款,但現在我希望能夠寫孩子的任何腳本語言如Python/Lua的等等。我怎樣才能做到這一點?我曾嘗試這樣的東西:
如果(EXECL( 「路徑蟒」, 「test.py」,(字符*)0)< 0)
但它只是似乎掛等待接收輸入?
有人可以幫助我嗎?我認爲PIPES可以和任何可以從STDIN讀取並返回STDOUT的Lua/Python進行通信?
UPDATE:
我已經取得了一些小的變化,現在,這裏是Python的文件:「NullFilter.py」,簡單地回聲它是什麼派:
#!/usr/bin/python
import sys
class NullFilter:
def execute(self):
#Read data from STDIN...
data = sys.stdin.read()
#Write data to STDOUT...
sys.stdout.write(data)
exit(0)
if __name__ == '__main__':
nf = NullFilter()
nf.execute()
而且現在的C代碼調用使用它:
...
if (execl("/usr/bin/python","./NullFilter.py","./NullFilter.py",NULL, (char *) 0) < 0)
puts("execl error...\n");
...
當我現在運行它,我可以輸入文本,標準輸入,但是必須擊中CRTL-C,看看發生了什麼:下面是結果:
[email protected]:~/Desktop/pipe example$ ./parent
hello
hello again
^CTraceback (most recent call last):
File "./NullFilter.py", line 17, in <module>
nf.execute()
File "./NullFilter.py", line 10, in execute
[email protected]:~/Desktop/pipe example$ data = sys.stdin.read()
KeyboardInterrupt
[email protected]:~/Desktop/pipe example$
更新2:
OK,所以我一直在玩弄一點,只是改變了Python代碼從 「sys.stdin.read()」 到 「sys.stdin.readline()」它似乎在一定程度上工作,但沒有完美...
#!/usr/bin/python
import sys
class NullFilter:
def execute(self):
#Read data from STDIN...
data = ""
for line in sys.stdin.readline():
data = data + line
#Write data to STDOUT...
sys.stdout.write(data)
exit(0)
if __name__ == '__main__':
nf = NullFilter()
nf.execute()
這是一個解決方法,但不完美的。任何其他想法如何讓STDIN讀取流UNBUFFERED?我已經在Python看了看SELECT模塊:
http://docs.python.org/library/select.html
我也試圖通過「-u」到Python使「緩衝」,但仍然沒有運氣;-(
但可以肯定這不能這麼難嗎?
林頓
只是出於好奇,你爲什麼不使用Python提供了與C接口API ?您可以使用它直接從C中調用Python代碼,而且非常靈活。 – avpx 2010-09-06 18:34:24
您好,我知道Python中的C API,但這不是我正在尋找的。該應用程序實際上是一個C應用程序,我只是*希望*因爲我正在使用PIPES,我可以用Python或Lua等其他語言編寫一些「用戶出口」......但無論如何;-) – 2010-09-07 07:25:34