2012-05-24 42 views
4

我有一個C++程序,它公開了一個Python接口來執行用戶的嵌入式Python腳本。如何將命令行參數作爲字符串傳遞給從C++執行的嵌入式Python腳本?

用戶插入要運行的Python腳本的路徑和命令行參數。 然後腳本通過

boost::python::exec_file(filename, main_globals, main_globals) 

執行要通過命令行參數的Python腳本,我們必須通過Python C-API函數

PySys_SetArgv(int args, char** argv) 

調用exec_file()之前對其進行設置。

但是這需要標記包含命令行參數的用戶字符串以獲取參數列表,然後通過PySys_SetArgv將它們傳回給Python解釋器。 這不僅僅是浪費時間,因爲通過這種方式,主C++程序必須負責標記命令行字符串,而不必知道後面的邏輯,該邏輯僅在自定義用戶的腳本中定義。

更加美好和更清潔的方法是這樣的事情在元代碼:

string command_line_args = '-v -p "filename" -t="anotherfile" --list="["a", "b"]" --myFunnyOpt' 
exec_file(filename, command_line_args, ...) 

我花了幾個小時在看加速和Python C-API文檔,但我沒有發現任何有用的東西。 您是否知道是否有辦法實現這一點,即將一整串命令行參數從C++傳遞到嵌入式Python腳本中?


更新:

正如史蒂夫的意見建議下面在這裏,我解決我的問題令牌化輸入字符串,以下https://stackoverflow.com/a/8965249/320369

在我來說,我使用:

// defining the separators 
std::string escape_char = "\\"; // the escape character 
std::string sep_char = " "; // empty space as separator 
std::string quote_char = ""; // empty string --> we don't want a quote char' 
boost::escaped_list_separator<char> sep(escape_char, sep_char, quote_char); 

,因爲我希望能夠解析包含字符串元組,以及像:

'--option-two=("A", "B")' 

,如果你使用:

escaped_list_separator<char> sep('\\', ' ', '"'); 

與原始文章中一樣,您不會正確地標記引用的字符串。

+2

「知道後面的邏輯,它只在自定義用戶的腳本中定義。」 - 這對我來說似乎是虛假的。 Python腳本*不包含用於標記命令行的邏輯,通常由Python啓動的shell(或等價物)完成。然後python解釋器會根據它從它自己的'main'參數或從什麼傳遞給'PySys_SetArgv'來構造'sys.argv'。在這種情況下,你等同於shell。恭喜! –

+2

這可能是相關的:http://stackoverflow.com/questions/8964307/c-how-to-break-not-parse-a-string-into-command-line-arguments。不是Boost.Program_Options的一部分,只是在處理之前將單個字符串拆分爲選項。 –

+0

我同意@Steve,你需要對自己的命令進行標記化,並將它們傳遞給python解釋器用sys.argv完成的方式。 – secumind

回答

1

由於您不需要執行外部文件,因此可以使用助手程序使shell命令爲您執行解析。你的助手程序可能是:

#include <stdio.h> 
int main (int argc, char *argv[]) 
{ 
    for (int i = 1; i < argc; ++i) printf("%s\n", argv[i]); 
    return 0; 
} 

然後你可以有你發送的參數的單串的幫助程序(可能使用popen)碼和讀回解析參數,每個精氨酸在單獨一行。

unparsed_line.insert(0, "./parser_helper "); 
FILE *helper = popen(unparsed_line.c_str(), "r"); 
std::vector<std::string> args; 
std::vector<const char *> argv; 
std::string arg; 
while (fgetstring(arg, helper)) { 
    args.push_back(arg); 
    argv.push_back(args.rbegin()->c_str()); 
} 
pclose(helper); 

fgetstring程序是我寫的是像fgetsstd::getline之間的交叉。它從FILE *一次讀取一行,填充std:string參數。

static bool 
fgetstring (std::string &s, FILE *in) 
{ 
    bool ok = false; 
    std::string r; 
    char buf[512]; 
    while (fgets(buf, sizeof(buf), in) != 0) { 
     ++ok; 
     r += buf; 
     if (*r.rbegin() == '\n') { 
      r.resize(r.size()-1); 
      break; 
     } 
    } 
    if (ok) s = r; 
    return ok; 
} 

我似乎記得有一個類似於這個例程的SO上的帖子,但我找不到它。如果我稍後再發現,我會更新我的帖子。

+0

感謝您的建議,併爲此+1。但最終我解決了這個http://stackoverflow.com/a/8965249/320369的問題,正如上面的@SteveJessop所建議的那樣。 – rmbianchi

+0

@rmbianchi:所有好東西,謝謝。 +1在你的問題上。 – jxh

相關問題