首页 > 解决方案 > Python 和 C 的单一源文件

问题描述

我正在写一个小模块,它将在 Python 和 C 中都使用。我可以编写一个 Python 版本和一个 C 版本,或者我可以编译 C 版本然后集成到 Python 中。但由于该模块主要是数学计算,在 Python 和 C 中基本相同,我正在考虑编写一个既可以在 Python 中导入又可以作为 C 源代码编译的文件。

这是一个基本技巧:

#if 1 /*
    write Python code here
''' */
    write C code here
#endif // '''

因此 Python 解释器将忽略 C 部分,而 C 编译器将忽略 Python 部分。

例如,以下内容foo.py

#if 1 /*
from math import sin, cos, sqrt
''' */
#include <math.h>
#endif // '''

#if 1 /*
def rotation(axis, angle):
    matrix = [0.] * 9
    ''' */
void rotation(double *axis, double angle, double *matrix) {
    double sa, ca, ia, r, x, y, z, xx, yy, zz;
    double cayz, caxz, caxy, iayz, iaxy, iaxz, sax, say, saz;
#endif // '''
    sa = sin(angle);
    ca = cos(angle);
    ia = 1. - ca;
    r = sqrt(axis[0] * axis[0] + axis[1] * axis[1] + axis[2] * axis[2]);
    x = axis[0] / r;
    y = axis[1] / r;
    z = axis[2] / r;
    xx = x * x;
    yy = y * y;
    zz = z * z;
    cayz = ca * (yy + zz);
    caxz = ca * (xx + zz);
    caxy = ca * (xx + yy);
    iayz = ia * y * z;
    iaxz = ia * x * z;
    iaxy = ia * x * y;
    sax = sa * x;
    say = sa * y;
    saz = sa * z;
    matrix[0] = cayz + xx;
    matrix[1] = iaxy - saz;
    matrix[2] = iaxz + say;
    matrix[3] = iaxy + saz;
    matrix[4] = caxz + yy;
    matrix[5] = iayz - sax;
    matrix[6] = iaxz - say;
    matrix[7] = iayz + sax;
    matrix[8] = caxy + zz;
#if 1 /*
    return matrix
''' */
    }
#endif // '''

在 Python 中:

from foo import rotation

print(rotation([1., 2., 3.], 4.))

在 C 中:

#include "foo.py"

int main() {
    double axis[3] = {1., 2., 3.};
    double angle = 4.;
    double matrix[9];
    rotation(axis, angle, matrix);
    printf("[%lf, %lf, %lf, %lf, %lf, %lf, %lf, %lf, %lf]",
           matrix[0], matrix[1], matrix[2],
           matrix[3], matrix[4], matrix[5],
           matrix[6], matrix[7], matrix[8]);
    return 0;
}

现在我想知道是否可以更进一步,使用一些更好的模式(例如宏)来定义:

或其他一些改进。

标签: pythoncmacros

解决方案


这个提议的根本问题是在编译 C 的同时解释 Python。

当您将 C 源代码通过预处理器一次时,这是 C 构建工具链的默认行为,对于 Python,您必须构建一个工具,将 .py 文件通过 C 预处理器,然后通过每次你想运行代码时输出到 Python 解释器。

您的运行时将需要 Python 解释器和您的特殊工具,并且代码将不再可移植到没有这种依赖关系的系统。

这是一个不存在的问题的复杂解决方案。


推荐阅读