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

使用ctypes调用C++返回二维数组报访问违规错误求解

错误根因

空指针访问错误是C++和Python两端的类型、内存布局、返回值不匹配共同导致的,核心错误点如下:

C++端错误

  1. 函数嵌套定义:在group_coordinates函数内部重复定义同名函数,属于语法错误,编译出来的函数逻辑不符合预期。
  2. 入参类型不匹配:Numpy的二维数组在内存中是连续存储的一维块,不是int**二级指针,用二级指针取值相当于把第一个元素的值当地址访问,直接触发空指针。
  3. 数组长度获取错误:sizeof(coordinates)拿到的是指针本身的大小(64位环境下为8字节),不是传入数组的元素个数。
  4. 返回值类型不兼容:ctypes不支持直接解析C++的vector<tuple<int,int>>类型,直接返回的内存布局完全无法被Python识别。
  5. 缺少mean_xy函数定义,代码本身无法编译通过。

Python端错误

  1. 函数名不匹配:加载dll之后调用的是c_lib.method,但C++导出的函数名是group_coordinates。
  2. 入参维度缺失:仅传了数组和max_deviation,没有传递数组长度,C++端无法识别传入的坐标点总数。
  3. 返回值处理错误:直接返回C++栈上的内存会被自动释放,就算拿到指针也是野指针,需要手动在堆上分配返回数组,同时把数组长度通过出参返回给Python。

修正后代码

C++端代码

#include <vector>
#include <tuple>
#include <cmath>

using namespace std;

// 补全缺失的mean_xy函数,可根据需求调整逻辑
tuple<int, int> mean_xy(vector<int>& x_list, vector<int>& y_list) {
    long long sum_x = 0, sum_y = 0;
    int len = x_list.size();
    for (int i = 0; i < len; i++) {
        sum_x += x_list[i];
        sum_y += y_list[i];
    }
    return make_tuple((int)(sum_x / len), (int)(sum_y / len));
}

extern "C" {
// 调整接口:入参为连续存储的int64一维数组(对应numpy二维数组)、坐标点个数、最大偏差
// 出参p_out_len用来返回结果数组的长度,返回值是堆上分配的int64数组,每个坐标占2个元素
__declspec(dllexport) long long* group_coordinates(long long* coordinates, int point_count, int max_deviation, int* p_out_len) {
    vector<vector<int>> mean_x_groups = {{(int)coordinates[0]}};
    vector<vector<int>> mean_y_groups = {{(int)coordinates[1]}};
    vector<tuple<int, int>> grouped_coordinates;
    
    int mean_x, mean_y;
    // 遍历所有坐标点,i从1开始,第一个点已经完成初始化
    for(int i = 1; i < point_count; i++) {
        int x = (int)coordinates[i*2];
        int y = (int)coordinates[i*2 + 1];
        bool found = false;
        // 检查所有已有分组
        for(int index = 0; index < mean_x_groups.size(); index++) {
            tie(mean_x, mean_y) = mean_xy(mean_x_groups[index], mean_y_groups[index]);
            if (abs(x - mean_x) <= max_deviation && abs(y - mean_y) <= max_deviation) {
                mean_x_groups[index].push_back(x);
                mean_y_groups[index].push_back(y);
                found = true;
                break;
            }
        }
        // 未找到匹配分组则新建分组
        if (!found) {
            mean_x_groups.push_back({x});
            mean_y_groups.push_back({y});
        }
    }
    
    // 生成结果
    for (int index = 0; index < mean_x_groups.size(); index++) {
        tie(mean_x, mean_y) = mean_xy(mean_x_groups[index], mean_y_groups[index]);
        grouped_coordinates.push_back(make_tuple(mean_x, mean_y));
    }
    
    // 堆上分配返回数组,用完需要手动释放
    *p_out_len = grouped_coordinates.size();
    long long* res = new long long[*p_out_len * 2];
    for (int i = 0; i < *p_out_len; i++) {
        res[i*2] = get<0>(grouped_coordinates[i]);
        res[i*2 + 1] = get<1>(grouped_coordinates[i]);
    }
    return res;
}

// 提供内存释放接口,避免内存泄漏
__declspec(dllexport) void free_mem(long long* p) {
    delete[] p;
}
}

Python端代码

import ctypes
import numpy as np

c_lib = ctypes.cdll.LoadLibrary(r"C:\Users\~user~\Desktop\~folder~\file.dll")

# 配置函数类型
c_lib.group_coordinates.restype = ctypes.POINTER(ctypes.c_int64)
c_lib.group_coordinates.argtypes = [
    np.ctypeslib.ndpointer(dtype=ctypes.c_int64, ndim=2, flags='C_CONTIGUOUS'),
    ctypes.c_int,
    ctypes.c_int,
    ctypes.POINTER(ctypes.c_int)
]
c_lib.free_mem.argtypes = [ctypes.POINTER(ctypes.c_int64)]

# 构造输入
x = [[0,1], [2,3], [1,1], [86,100], [87,99], [100,100]] 
array = np.array(x, dtype = ctypes.c_int64)
point_count = array.shape[0]
max_deviation = 5
out_len = ctypes.c_int()

# 调用函数
res_ptr = c_lib.group_coordinates(array, point_count, max_deviation, ctypes.byref(out_len))

# 指针转numpy数组
res_array = np.ctypeslib.as_array(res_ptr, shape=(out_len.value, 2)).copy()
print(res_array)

# 释放C++端分配的内存
c_lib.free_mem(res_ptr)

注意事项

  • 编译C++代码时需选择和Python环境一致的架构(同是64位或同是32位),否则会调用失败。
  • 如不想手动处理内存和类型匹配,可改用pybind11做C++ Python绑定,开发成本更低。

内容的提问来源于stack exchange,提问作者Marshall Merz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 20:15:06