2010-12-12 20 views
4

如果您在C輸出了大量的值在Python的字典,有沒有更好的(更快且不易出錯)的方式來做到這一點比:Python/C:一次解析所有值以返回Python?

return Py_BuildValue("{s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:(i,i,i,i),s:(i,i,i,i),s:(i,i,i,i)}", 
      "jd\0",    spa.jd, //Julian day 
      "jc\0",    spa.jc, //Julian century 
      "jde\0",   spa.jde, //Julian ephemeris day 
      "jce\0",   spa.jce, //Julian ephemeris century 
      "jme\0",   spa.jme, //Julian ephemeris millennium 
      "l\0",    spa.l, //earth heliocentric longitude [degrees] 
      "b\0",    spa.b, //earth heliocentric latitude [degrees] 
      "r\0",    spa.r,  //earth radius vector [Astronomical Units, AU] 
      "theta\0",   spa.theta, //geocentric longitude [degrees] 
      "beta\0",   spa.beta, //geocentric latitude [degrees] 
      "x0\0",    spa.x0, //mean elongation (moon-sun) [degrees] 
      "x1\0",    spa.x1, //mean anomaly (sun) [degrees] 
      "x2\0",    spa.x2, //mean anomaly (moon) [degrees] 
      "x3\0",    spa.x3, //argument latitude (moon) [degrees] 
      "x4\0",    spa.x4, //ascending longitude (moon) [degrees] 
      "del_psi\0",  spa.del_psi, //nutation longitude [degrees] 
      "del_epsilon\0", spa.del_epsilon, //nutation obliquity [degrees] 
      "epsilon0\0",  spa.epsilon0, //ecliptic mean obliquity [arc seconds] 
      "epsilon\0",  spa.epsilon, //ecliptic true obliquity [degrees] 
      "del_tau\0",  spa.del_tau, //aberration correction [degrees] 
      "lamda\0",   spa.lamda, //apparent sun longitude [degrees] 
      "nu0\0",   spa.nu0, //Greenwich mean sidereal time [degrees] 
      "nu\0",    spa.nu, //Greenwich sidereal time [degrees] 
      "alpha\0",   spa.alpha, //geocentric sun right ascension [degrees] 
      "delta\0",   spa.delta, //geocentric sun declination [degrees] 
      "h\0",    spa.h, //observer hour angle [degrees] 
      "xi\0",    spa.xi, //sun equatorial horizontal parallax [degrees] 
      "del_alpha\0",  spa.del_alpha, //sun right ascension parallax [degrees] 
      "delta_prime\0", spa.delta_prime, //topocentric sun declination [degrees] 
      "alpha_prime\0", spa.alpha_prime, //topocentric sun right ascension [degrees] 
      "h_prime\0",  spa.h_prime, //topocentric local hour angle [degrees], 
      "h0_prime\0",  spa.h0_prime, 
      "delta_zero\0",  spa.delta_zero, 
      "e0\0",    spa.e0, //topocentric elevation angle (uncorrected) [degrees] 
      "del_e\0",   spa.del_e, //atmospheric refraction correction [degrees] 
      "e\0",    spa.e, //topocentric elevation angle (corrected) [degrees] 
      "eot\0",   spa.eot, //equation of time [minutes] 
      "srha\0",   spa.srha, //sunrise hour angle [degrees] 
      "ssha\0",   spa.ssha, //sunset hour angle [degrees] 
      "sta\0",   spa.sta, //sun transit altitude [degrees] 
      "zenith\0",   spa.zenith, //topocentric zenith angle [degrees] 
      "azimuth180\0",  spa.azimuth180, //topocentric azimuth angle (westward from south) [-180 to 180 degrees] 
      "azimuth\0",  spa.azimuth, //topocentric azimuth angle (eastward from north) [ 0 to 360 degrees] 
      "incidence\0",  spa.incidence, //surface incidence angle [degrees] 
      "_suntransit\0", spa.suntransit, //local sun transit time (or solar noon) [fractional hour] 
      "_sunrise\0",  spa.sunrise, //local sunrise time (+/- 30 seconds) [fractional hour] 
      "_sunset\0",  spa.sunset, //local sunset time (+/- 30 seconds) [fractional hour] 
      "sunrise\0",  sunrise_hour, sunrise_min, sunrise_sec, sunrise_microsec, 
      "sunset\0",   sunset_hour, sunset_min, sunset_sec, sunset_microsec, 
      "noon\0",   transit_hour, transit_min, transit_sec, transit_microsec 
      ); 
+0

如果你在幾個地方有這種模式,[X宏](http://en.wikipedia.org/wiki/C_preprocessor#X-Macros)可能會有所幫助。 – delnan 2010-12-12 21:44:52

+3

你不需要像那樣明確地寫'\ 0'; C中的字符串文字已經意味着一個空終止符 - 如果你寫了「」foo「',那麼四個字節{'f','o','o',0}被存儲在靜態存儲器中。 – 2010-12-12 21:53:24

回答

2

我同意@Martin v。Löwis關於使用C預處理器及其宏功能來減輕至少一些設置和維護類似於您所做的事情的負擔。如果您正確定義這些宏,您可以安排將所有定義信息放在單個頭文件中的一個位置,並避免重複自己。

基本上,您需要兩條關於每個項目或關鍵字&值的信息才能進入您正在構建的字典。一個是Py_BuildValue()的格式字符串參數,第二個是密鑰的來源和關聯值。

通過定義並重新定義任務所需的宏,可以提取這兩組信息中的每一組信息。對於您的示例,可以創建以下頭文件。請注意,如何定義兩個不同宏集中的一個,具體取決於FORMAT還是FIELDS是在#included時定義的。

// builddict.h -- for defining Py_BuildValue() arguments 

// define apppropriate macros for current usage 
#ifdef FORMAT 
    #define SPA_FIELD_LAST(FIELD)   "s:d" 
    #define SPA_FIELD(FIELD)    SPA_FIELD_LAST(FIELD)", " 
    #define TIME_FIELD_LAST(NAME)   "s:(i,i,i,i)" 
    #define TIME_FIELD(NAME)    TIME_FIELD_LAST(NAME)", " 
    #define TIME_KEY_FIELD_LAST(KEY,NAME) "s:(i,i,i,i)" 
    #define TIME_KEY_FIELD(KEY,NAME)  TIME_KEY_FIELD_LAST(KEY,NAME)", " 
    #undef FORMAT 
#elif defined FIELDS 
    #define SPA_FIELD_LAST(FIELD)   #FIELD, spa.FIELD 
    #define SPA_FIELD(FIELD)    SPA_FIELD_LAST(FIELD), 
    #define TIME_FIELD_LAST(NAME)   #NAME, NAME##_hour, NAME##_min, NAME##_sec, NAME##_microsec 
    #define TIME_FIELD(NAME)    TIME_FIELD_LAST(NAME), 
    #define TIME_KEY_FIELD_LAST(KEY,NAME) #KEY, NAME##_hour, NAME##_min, NAME##_sec, NAME##_microsec 
    #define TIME_KEY_FIELD(KEY,NAME)  TIME_KEY_FIELD_LAST(KEY,NAME), 
    #undef FIELDS 
#else 
    #error neither FORMAT nor FIELDS usage macros are defined 
#endif 

SPA_FIELD(jd)    // Julian day 
SPA_FIELD(jc)    // Julian century 
SPA_FIELD(jde)    // Julian ephemeris day 
SPA_FIELD(jce)    // Julian ephemeris century 
SPA_FIELD(jme)    // Julian ephemeris millennium 
SPA_FIELD(l)    // earth heliocentric longitude [degrees] 
SPA_FIELD(b)    // earth heliocentric latitude [degrees] 
SPA_FIELD(r)    // earth radius vector [Astronomical Units) AU] 
SPA_FIELD(theta)   // geocentric longitude [degrees] 
SPA_FIELD(beta)    // geocentric latitude [degrees] 
SPA_FIELD(x0)    // mean elongation (moon-sun) [degrees] 
SPA_FIELD(x1)    // mean anomaly (sun) [degrees] 
SPA_FIELD(x2)    // mean anomaly (moon) [degrees] 
SPA_FIELD(x3)    // argument latitude (moon) [degrees] 
SPA_FIELD(x4)    // ascending longitude (moon) [degrees] 
SPA_FIELD(del_psi)   // nutation longitude [degrees] 
SPA_FIELD(del_epsilon)  // nutation obliquity [degrees] 
SPA_FIELD(epsilon0)   // ecliptic mean obliquity [arc seconds] 
SPA_FIELD(epsilon)   // ecliptic true obliquity [degrees] 
SPA_FIELD(del_tau)   // aberration correction [degrees] 
SPA_FIELD(lamda)   // apparent sun longitude [degrees] 
SPA_FIELD(nu0)    // Greenwich mean sidereal time [degrees] 
SPA_FIELD(nu)    // Greenwich sidereal time [degrees] 
SPA_FIELD(alpha)   // geocentric sun right ascension [degrees] 
SPA_FIELD(delta)   // geocentric sun declination [degrees] 
SPA_FIELD(h)    // observer hour angle [degrees] 
SPA_FIELD(xi)    // sun equatorial horizontal parallax [degrees] 
SPA_FIELD(del_alpha)  // sun right ascension parallax [degrees] 
SPA_FIELD(delta_prime)  // topocentric sun declination [degrees] 
SPA_FIELD(alpha_prime)  // topocentric sun right ascension [degrees] 
SPA_FIELD(h_prime)   // topocentric local hour angle [degrees]) 
SPA_FIELD(h0_prime) 
SPA_FIELD(delta_zero) 
SPA_FIELD(e0)    // topocentric elevation angle (uncorrected) [degrees] 
SPA_FIELD(del_e)   // atmospheric refraction correction [degrees] 
SPA_FIELD(e)    // topocentric elevation angle (corrected) [degrees] 
SPA_FIELD(eot)    // equation of time [minutes] 
SPA_FIELD(srha)    // sunrise hour angle [degrees] 
SPA_FIELD(ssha)    // sunset hour angle [degrees] 
SPA_FIELD(sta)    // sun transit altitude [degrees] 
SPA_FIELD(zenith)   // topocentric zenith angle [degrees] 
SPA_FIELD(azimuth180)  // topocentric azimuth angle (westward from south) [-180 to 180 degrees] 
SPA_FIELD(azimuth)   // topocentric azimuth angle (eastward from north) [ 0 to 360 degrees] 
SPA_FIELD(incidence)  // surface incidence angle [degrees] 
SPA_FIELD(suntransit)  // local sun transit time (or solar noon) [fractional hour] 
SPA_FIELD(sunrise)   // local sunrise time (+/- 30 seconds) [fractional hour] 
SPA_FIELD(sunset)   // local sunset time (+/- 30 seconds) [fractional hour] 
TIME_FIELD(sunrise) 
TIME_FIELD(sunset) 
TIME_KEY_FIELD_LAST(noon, transit) // must use a xxx_LAST macro on last one 

// clean up to prevent warnings about redefining macros 
#undef SPA_FIELD_LAST 
#undef SPA_FIELD 
#undef TIME_FIELD_LAST 
#undef TIME_FIELD 
#undef TIME_KEY_FIELD_LAST 
#undef TIME_KEY_FIELD 

一旦你擁有這一切成立,你build_dict()功能,成爲東西相當短的,獨立的什麼字典的實際內容將會是:

// build format string using header 
char format_string[] = "{" 
    #define FORMAT 
    #include "builddict.h" 
"}"; 

// use header again to build list of fields 
PyObject* build_dict(SPA spa) 
{ 
    return Py_BuildValue(format_string, 
     #define FIELDS 
     #include "builddict.h" 
    ); 
} 

雖然這並不完全自動化這個過程,但是可以幫助很多。可能還有其他文本處理或C接口工具可用(或者您可以自己編寫)以進一步幫助您創建此單個頭文件,因爲它具有非常統一的格式。

2

您可以使用宏:

#define ADD_FIELD(F) PyDict_SetItemString(d, #F, spa.F) 
ADD_FIELD(jd); 
ADD_FIELD(jc); 
... 

這將防止字符串名稱錯誤,格式字符串。 未列出所有字段的錯誤不容易阻止AFAICT。

此外,你可以刪除尾隨\0;它不起作用。

1

如果需要對幾個結構,那麼我可能會寫一個小的Python腳本通過從.H(例如,通過一個特殊的標記註釋閱讀結構定義生成的代碼是什麼,你所需要的結構和字段導出爲字典)......但是,所示情況下的最後三個字段需要手動添加到字典中。

我不會那樣做,只爲一個結構,特別是如果結構穩定。

您是否考慮導出對象而不是使用例如使用SIP的字典?