如何在Python C扩展中获取C类型大小并传入编译参数?
Python C扩展中获取C类型大小的解决方案
Python 没有像 Ruby mkmf 或 Autoconf 的 AC_CHECK_SIZEOF 那样直接内置的类型大小检测方法,但可以基于 distutils/setuptools 的编译能力自行实现,核心逻辑是编译一段测试代码并运行以获取目标类型的 sizeof 值。
实现步骤
1. 编写类型大小检测函数
在 setup.py 中添加一个函数,利用 distutils.ccompiler 编译并运行测试代码:
from distutils.ccompiler import new_compiler import os import subprocess def get_sizeof_type(type_name, include_headers=None): include_headers = include_headers or [] compiler = new_compiler() # 构建测试代码,包含必要的头文件 header_lines = "\n".join([f"#include <{hdr}>" for hdr in include_headers]) test_code = f"""{header_lines} #include <stdio.h> int main() {{ printf("%zu", sizeof({type_name})); return 0; }} """ # 写入临时测试文件 temp_c = "sizeof_temp.c" with open(temp_c, "w") as f: f.write(test_code) try: # 编译测试程序 obj_files = compiler.compile([temp_c]) exe_file = compiler.link_executable(obj_files, "sizeof_temp") # 运行程序并捕获输出 size_output = subprocess.check_output([exe_file]).decode().strip() return int(size_output) finally: # 清理临时文件 for f in [temp_c] + obj_files + [exe_file]: if os.path.exists(f): os.remove(f)
2. 在setup中使用检测结果
调用上述函数获取类型大小,再传入编译参数:
from setuptools import setup, Extension # 替换为你需要检测的类型和对应的头文件 sizeof_mytype = get_sizeof_type("MyType", include_headers=["mytype.h"]) setup( name="my_c_extension", ext_modules=[ Extension( "my_c_extension", sources=["my_extension.c"], extra_compile_args=[f"-DSIZEOF_MYTYPE={sizeof_mytype}"] ) ] )
关键注意事项
- 如果检测的是自定义类型(如你示例中的
MyType),必须通过include_headers参数传入对应的头文件,否则编译会失败。 - 使用
%zu作为printf的格式符是 C 标准写法,适配大多数现代编译器和平台(包括32位/64位系统)。 - 临时文件清理逻辑确保不会在项目目录留下编译残留,避免干扰后续构建。
内容的提问来源于stack exchange,提问作者jjg
相关产品推荐
相关产品推荐

