4

C から Python の dict に多くの値を出力している場合、次の方法よりも優れた (より迅速でエラーが発生しにくい) 方法はありますか?

    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
            );
4

4 に答える 4

2

ほとんどの値が から来ているように見えることを考えると、オブジェクト内spaの他の緩いプロパティと一緒にそれをカプセル化し、それを返すことをお勧めします。また、.datetime.time

于 2010-12-12T21:45:58.883 に答える
2

マクロを使用できます。

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

これにより、文字列名とフォーマット文字列の間違いを防ぐことができます。すべてのフィールドをリストしないという間違いは、AFAICT を防ぐのは簡単ではありません。

また、末尾の\0;を削除することもできます。それは目的を果たしません。

于 2010-12-12T21:52:54.170 に答える
2

Cプリプロセッサとそのマクロ機能を使用して、あなたがやっていることのようなものを設定して維持する負担の少なくとも一部を軽減することについて、@Martin v. Löwisに同意します。これらのマクロを適切に定義すると、すべての定義情報を 1 つのヘッダー ファイル内の 1 つの場所に配置して、繰り返しを避けることができます。

基本的に、作成中のディクショナリに入れる各項目またはキーと値のペアについて 2 つの情報が必要です。1 つは のフォーマット文字列引数に入れられるものでPy_BuildValue()、2 番目はキーのソースとそれに関連付けられた値です。

これら 2 つの情報セットのそれぞれを抽出するには、タスクで必要に応じて使用されるマクロを定義してから再定義します。たとえば、次のヘッダー ファイルを作成できます。dの時点で定義されていたかどうFORMATかに応じて、2 つの異なるマクロ セットのいずれかがどのように定義されるかに注意してください。FIELDS#include

// 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 インターフェース ツールが利用可能 (または独自に作成できる) である可能性があります。

于 2010-12-13T05:41:16.010 に答える
1

それがいくつかの構造体に必要な場合は、.h から構造体定義を読み取ることによって、このコードを生成するための小さな python スクリプトをおそらく作成します (たとえば、dicts としてエクスポートする必要がある構造体とフィールドは何かを特別なコメントでタグ付けすることによって)。 ) ... ただし、示されているケースの最後の 3 つのフィールドは、dict に手動で追加する必要があります。

特に構造体が安定している場合は、1つの構造体に対してだけ行うことはありません。

たとえば SIP を使用して、辞書の代わりにオブジェクトをエクスポートすることを検討しましたか?

于 2010-12-12T21:53:04.217 に答える