繁体   English   中英

当我调用 calloc 时,使用 ctypes 调用的 C Dll 返回错误

[英]C Dll called with ctypes returns error when I call calloc

当我的代码从 C DLL 调用 function 时,它会出现访问冲突错误。 function:

int* get_shader_points(int uv_x0, int uv_x1, int uv_y0, int uv_y1, float** triangles, int no_tri){
int max_no_point = ((uv_x1 - uv_x0) * (uv_y0 - uv_y1)) * 2;
int* points = (int*) calloc(NULL, sizeof(int) * max_no_point); // error here

if(points == NULL){
    return NULL;
}
int p_Id = 0;
for(int y = uv_y1; y < uv_y0; y++)
for(int x = uv_x0; x < uv_x1; x++){
    for(int tid = 0; tid < no_tri/3; tid += 3){
        if(isInside((int) triangles[tid][0], (int) triangles[tid][1], (int) triangles[tid+1][0], (int) triangles[tid+1][1], (int) triangles[tid+2][0], (int) triangles[tid+2][1], x, y)){
            //points[p_Id + 0] = x;
            //points[p_Id + 1] = y;
            //p_Id += 2;
        }
    }
}

return points;
}

我注释掉了它在数组中设置值的部分,因为这也在 python 中给了我一个 OSError

错误: OSError: exception: access violation writing 0x0000000000002C44

Python 代码:

lib = WinDLL("./util.dll")
uvx0, uvx1 = -30, 30
uvy0, uvy1 = 30, -30
triangles = [(-20, 10), (-10, 20), (0, 20), (40, 40), (100, 40), (40, 100)]
ptris = ((ctypes.c_float * 2) * len(triangles))(*triangles)
print(lib.get_shader_points(uvx0, uvx1, uvy0, uvy1, ptris, len(ptris)))

还应该注意的是,我被迫使用 python 中的 distutils 模块(使用 msvc)编译 c 代码,如果这可能会使 DLL 无法正常工作

我不得不做一些猜测来制作一个可重现的例子,并稍微更改了 function 调用的签名。 由于可以返回可变数量的点,因此需要一种方法来知道返回了多少点。 我还添加了一种释放分配的 memory 的方法:

测试.c

// To export functions of Windows DLLs
#ifdef _WIN32
#   define API __declspec(dllexport)
#else
#   define API
#endif

#include <stdlib.h>

// Added missing implementation...just returns true for everything...
int isInside(int x1, int y1, int x2, int y2, int x3, int y3, int x, int y) {
    return 1;
}

// float** is the wrong type for a 2D array (at least an easy one to make from Python)
// Also added output parameter for number of points returned.
API int* get_shader_points(int uv_x0, int uv_x1, int uv_y0, int uv_y1, float triangles[][2], int no_tri, int *no_point) {
    int max_no_point = ((uv_x1 - uv_x0) * (uv_y0 - uv_y1)) * 2;
    // calloc was called incorrectly, it takes a count and size.
    int* points = calloc(max_no_point, sizeof(int));
    if(points == NULL) {
        return NULL;
    }

    int p_Id = 0;
    for(int y = uv_y1; y < uv_y0; y++)
        for(int x = uv_x0; x < uv_x1; x++) {
            for(int tid = 0; tid < no_tri/3; tid += 3) {
                if(isInside((int) triangles[tid][0], (int) triangles[tid][1], (int) triangles[tid+1][0], (int) triangles[tid+1][1], (int) triangles[tid+2][0], (int) triangles[tid+2][1], x, y)) {
                    points[p_Id + 0] = x;
                    points[p_Id + 1] = y;
                    p_Id += 2;
                }
            }
        }

    *no_point = p_Id; // return number of points
    return points;    // and the allocated array
}

API void free_points(int* points) {
    free(points);
}

测试.py

import ctypes as ct

lib = ct.CDLL('./test')  # WinDLL is for 32-bit __stdcall functions
                         # although either works on 64-bit.
lib.get_shader_points.argtypes = ct.c_int, ct.c_int, ct.c_int, ct.c_int, ct.POINTER(ct.c_float * 2), ct.c_int, ct.POINTER(ct.c_int)
lib.get_shader_points.restype = ct.POINTER(ct.c_int)  # Need, or default return value is c_int.
lib.free_points.argtypes = ct.POINTER(ct.c_int), 
lib.free_points.restype = None

def get_shader_points(uvx0, uvx1, uvy0, uvy1, triangles):
    ptris = ((ct.c_float * 2) * len(triangles))(*triangles)
    no_point = ct.c_int() # storage for output parameter
    result = lib.get_shader_points(uvx0, uvx1, uvy0, uvy1, ptris, len(ptris), ct.byref(no_point))
    retval = result[:no_point.value] # slicing retrieves a list of points of the correct size
    lib.free_points(result) # free the allocation.
    return retval

uvx0, uvx1 = -3, 3  # reduced range for smaller output since isInside() returns everything right now
uvy0, uvy1 = 3, -3
triangles = [(-20, 10), (-10, 20), (0, 20), (40, 40), (100, 40), (40, 100)]

points = get_shader_points(uvx0, uvx1, uvy0, uvy1, triangles)
print(len(points))
print(points)

Output:

72
[-3, -3, -2, -3, -1, -3, 0, -3, 1, -3, 2, -3, -3, -2, -2, -2, -1, -2, 0, -2, 1, -2, 2, -2, -3, -1, -2, -1, -1, -1, 0, -1, 1, -1, 2, -1, -3, 0, -2, 0, -1, 0, 0, 0, 1, 0, 2, 0, -3, 1, -2, 1, -1, 1, 0, 1, 1, 1, 2, 1, -3, 2, -2, 2, -1, 2, 0, 2, 1, 2, 2, 2]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM