ctypes结构包含垃圾/不正确的d

2024-09-29 22:31:08 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个C++ DLL(64位),它作为一个双指针指向一个结构(即指向一个结构数组的指针)。函数动态分配结构数组,然后填充每个结构元素(元素包括:整数、浮点、双精度、静态数组、另一个结构和动态分配的数组)。在

我创建了一个python类来模拟结构(所有数据元素)。但是,当我调用C++函数时,CreateROIs(…)-从python中,我得到了结构中某些元素的垃圾/错误值。在

例如,我将得到ppMem[0].spic=24609435234

有趣的是,如果我把同样的数据结构传递给C++ DLL,并打印出C++中的元素,它们仍然是正确的(下面的这部分不提供函数/代码)。在

我假设在64位Python和C++ DLL之间移动数据时,数据类型(双倍/浮点)是一个问题。或者可能结构没有连续内存?我好像找不到它。。。不管怎样,任何帮助都是非常感谢的!在

这是我的代码,谢谢你的帮助!在

C++ dll代码:

// TriangleMesh struct where mesh is defined by vertices connected via triangles
// <summary>
extern "C"

struct MyDLL_API TriangleMesh
{
    int nbrVertices;
    int nbrTriangles;

    float* vertices;
    int* triangles;
};

extern "C"
struct MyDLL_API ROI 
{
    double xmm;
    double ymm;
    double zmm;
    double diameter;
    double level;
    double volume;
    double threshold;
    int isMesh;
    double mVol;
    double mass;
    double meanD;
    double dve;
    double dla;
    double dsa;
    double dla3D;
    double spike; 
    float sphere;

    float lais[6];  
    float sais[6];  
    float la3D[6];      

    TriangleMesh mesh;
};

extern "C" MyDLL_API
void CreateROIs(ROI** ppMem, int* NumROIs);

void CreateROIs(ROI** ppMem, int* NumROIs)
{
    *ppMem = (ROI *)malloc(sizeof(ROI) * (*NumROIs));

    for (int i = 0; i < *nbrNodules; i++)
    {
        (*ppMem)[i].xmm = double(i + 1.0);
        (*ppMem)[i].ymm = double(i + 1.0);
        (*ppMem)[i].zmm = double(i + 1.0);
        (*ppMem)[i].diameter = double(i + 1.0);
        (*ppMem)[i].level = double(i + 1.0);
        (*ppMem)[i].volume= double(i + 1.0);
        (*ppMem)[i].threshold = double(i + 1.0);
        (*ppMem)[i].mVol= double(i + 1.0);
        (*ppMem)[i].mass = double(i + 1.0);
        (*ppMem)[i].meanD= double(i + 1.0);
        (*ppMem)[i].dve = double(i + 1.0);
        (*ppMem)[i].dla = double(i + 1.0);
        (*ppMem)[i].dsa = double(i + 1.0);
        (*ppMem)[i].dla3D = double(i + 10.0);
        (*ppMem)[i].spike = double(i + 1.0);
        (*ppMem)[i].sphere = double(i + 1.0);

        int arr_size = sizeof((*ppMem)[i].longAxis3D) / sizeof((*ppMem)[i].longAxis3D[0]);

        for (int j = 0; j < arr_size; j++)
        {
            float val = arr_size * i + j;
            (*ppMem)[i].lais[j] = val;
            (*ppMem)[i].sais[j] = val;
            (*ppMem)[i].la3D[j] = val;
        }


        (*ppMem)[i].meshWasCreatedByDll = int(i+1);
        (*ppMem)[i].segMesh.nbrVertices = int(rand() % 10 + 1);
        (*ppMem)[i].segMesh.nbrTriangles = int(rand() % 10 + 1);

        (*ppMem)[i].segMesh.vertices = (float *)malloc(sizeof(float) * (*ppMem)[i].segMesh.nbrVertices);
        (*ppMem)[i].segMesh.triangles = (int *)malloc(sizeof(int) * (*ppMem)[i].segMesh.nbrTriangles);

        for (int j = 0; j < (*ppMem)[i].segMesh.nbrVertices; j++)
        {
            (*ppMem)[i].segMesh.vertices[j] = float(j + 1);
        }

        for (int j = 0; j < (*ppMem)[i].segMesh.nbrTriangles; j++)
        {
            (*ppMem)[i].segMesh.triangles[j] = int(j + 1);
        }

    }
}

}

Python代码:

^{pr2}$

Tags: 代码元素数组float结构intdoublevertices
1条回答
网友
1楼 · 发布于 2024-09-29 22:31:08

你的两个结构至少有两个不匹配。在

我不知道哪个,如果两者都是相关的,因为你的垃圾看起来在一个字段中,叫做“{< CD1>}”,它没有出现在C++结构或cType……/P>中。


首先,有两个字段无序:

double threshold;
int isMesh;
double mVol;

对比

^{pr2}$

这看起来没什么大不了的,但是一旦将对齐驱动的填充放入混合中,可以想象,这可能会导致所有后续字段的大小都减少4个字节。在


然后,您对所有这些数组使用了错误的类型:

float lais[6];  
float sais[6];  
float la3D[6];      

对比

("lais", c_double*6),   
("said", c_double*6), 
("la3D", c_double*6),       

float是32位;c_double是64位。lais[0]是一个由lais[0]和{}打包在一起的垃圾double,lais[4]是{}和{}打包在一起,la3D[4]是堆中超过结构结尾的64个随机位。如果幸运的话,当您试图读取它时会得到一个segfault,但是如果没有,您就很难调试垃圾。在


对于像这样非常复杂的结构,我通常不相信自己能够在不犯至少三倍于您的错误的情况下手动编写ctypes版本。或者偶尔编写一个Python(或者快速解析)来生成代码。对于像CoreFoundation和Win32 headers这样的东西,它们有成千上万个可笑的巨大结构,都是以非常严格和可靠的风格编写的,我有反复使用的脚本。在

相关问题 更多 >

    热门问题