🔴 数组递过去,C 那边改得到

👁️ 2 人浏览 💬 0 人评论 ❤️ 添加收藏

🔴 这一节的 Python 题会**在运行时调 gcc 现编一个 .so,再用 ctypes 加载进来**——真的跨语言调用,不是假装。判题机需要 gcc、一个可写的临时目录,以及允许 Python 起子进程。⚠️ 这条路线**一个答案都不是耗时**。耗时跟机器、跟负载、跟编译器都有关,换台机器数字就变了。**能当答案的只有"走了多少步"和"两边结果一不一样"。**

import ctypes, os, subprocess, tempfile

def build_c(src, name="m"):
    """把一段 C 现场编成 .so,交回加载好的库。
       判题机需要 gcc 和一个可写的临时目录。"""
    d = tempfile.mkdtemp()
    c_path = os.path.join(d, name + ".c")
    so_path = os.path.join(d, name + ".so")
    with open(c_path, "w") as f:
        f.write(src)
    subprocess.run(["gcc", "-shared", "-fPIC", "-O2", "-o", so_path, c_path],
                   check=True, capture_output=True)
    return ctypes.CDLL(so_path)

C_SRC = r"""
long sum_arr(const int *a, int n) { long s = 0; for (int i = 0; i < n; i++) s += a[i]; return s; }
void double_all(int *a, int n) { for (int i = 0; i < n; i++) a[i] *= 2; }
"""

lib = build_c(C_SRC)
lib.sum_arr.argtypes = [ctypes.POINTER(ctypes.c_int), ctypes.c_int]
lib.sum_arr.restype = ctypes.c_long
lib.double_all.argtypes = [ctypes.POINTER(ctypes.c_int), ctypes.c_int]
lib.double_all.restype = None

data = [1, 2, 3, 4]
Arr = ctypes.c_int * len(data)      # 先造一块 C 认得的连续内存
buf = Arr(*data)

s = lib.sum_arr(buf, len(data))     # 只读:C 那边不改
lib.double_all(buf, len(data))      # 可写:C 那边直接改这块内存

print(f"{s}/{buf[0]}/{buf[3]}/{int(list(buf) == [2, 4, 6, 8])}")
提交你的答案
请登录后提交答案。
去登录
代码编辑器
Ctrl + Enter 运行
本次输入:
输出:

                        
👩‍🏫
AI
💬 题目评论

全部评论