You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Cython转换接收并返回std::vector的C++函数?

解决方案

前置准备:补充C++头文件

首先需要为你的C++函数创建头文件cpp_func.h,供Cython调用:

#include <vector>

std::vector<std::vector<float>> my_cpp_function(const size_t& p_num,
                                                const std::vector<float>& x,
                                                const std::vector<std::vector<float>>& table);

问题1:Numpy数组转C++ std::vector

Numpy数组的memoryview无法直接传递给接收std::vector的C++函数,必须进行类型转换。我们可以用memcpy实现高效拷贝,避免循环赋值的开销:

问题2:C++二维vector转memoryview

二维std::vector的内存是非连续的(每个子vector独立分配),而Numpy/memoryview要求连续内存。需要先创建连续内存的Numpy数组,再将vector数据拷贝进去。

问题3:高效转换优化

  • 输入侧:用memcpy替代循环赋值,提前调用vector.reserve()避免扩容时的内存重分配
  • 输出侧:同样用memcpy完成数据拷贝,返回的memoryview可直接被Numpy复用,无需额外拷贝

修改后的完整Cython代码(cython_v1.pyx)

import numpy as np
cimport numpy as np
import cython
from libcpp.vector cimport vector
from libc.string cimport memcpy

# 声明C++函数接口
cdef extern from "cpp_func.h":
    vector[vector[float]] my_cpp_function(const size_t& p_num,
                                         const vector[float]& x,
                                         const vector[vector[float]]& table)

@cython.boundscheck(False)
@cython.wraparound(False)
cpdef float[:, ::1] my_cython_func(size_t p_num, float[:] x, float[:, ::1] table):
    # 1. 转换一维输入x为C++ vector
    cdef vector[float] cpp_x
    cpp_x.reserve(x.shape[0])
    memcpy(&cpp_x[0], x.data(), x.shape[0] * sizeof(float))

    # 2. 转换二维输入table为C++二维vector
    cdef vector[vector[float]] cpp_table
    cpp_table.reserve(table.shape[0])
    cdef int i, cols = table.shape[1]
    for i in range(table.shape[0]):
        cdef vector[float] row
        row.reserve(cols)
        memcpy(&row[0], table[i].data(), cols * sizeof(float))
        cpp_table.push_back(row)

    # 调用C++核心函数
    cdef vector[vector[float]] cpp_H = my_cpp_function(p_num, cpp_x, cpp_table)

    # 3. 转换C++输出为连续内存的memoryview
    cdef int rows = cpp_H.size()
    if rows == 0:
        return np.empty((0, 0), dtype=np.float32).view()
    
    cdef int out_cols = cpp_H[0].size()
    # 创建连续内存的Numpy数组
    cdef np.ndarray[float, ndim=2, mode="c"] result_np = np.empty((rows, out_cols), dtype=np.float32)
    cdef float[:, ::1] result_view = result_np

    # 高效拷贝每一行数据
    for i in range(rows):
        memcpy(&result_view[i, 0], cpp_H[i].data(), out_cols * sizeof(float))

    return result_view

编译脚本(setup.py)

用于将Cython和C++代码编译为Python可导入模块:

from setuptools import setup, Extension
from Cython.Build import cythonize
import numpy as np

ext = Extension(
    "cython_v1",
    sources=["cython_v1.pyx", "cpp_func.cpp"],
    language="c++",
    include_dirs=[np.get_include()],
    extra_compile_args=["-O3"],  # 开启编译优化
)

setup(ext_modules=cythonize(ext))

编译与调用

  1. 编译模块:运行python setup.py build_ext --inplace
  2. Python调用代码无需修改,np.asarray(my_cython_func(...))会直接复用memoryview的内存,无额外拷贝开销

内容的提问来源于stack exchange,提问作者Ong Beng Seong

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 09:22:17