首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ctypes - structure包含垃圾/不正确的数据

ctypes - structure包含垃圾/不正确的数据
EN

Stack Overflow用户
提问于 2018-08-23 07:04:03
回答 1查看 395关注 0票数 0

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

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

例如,我将获取ppMem.spic=24609435234

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

我假设这是在64位python和C++ DLL之间移动数据时数据类型(双精度/浮点数)的问题。或者可能对结构没有连续的内存?我似乎找不到它...无论如何,任何帮助都是非常感谢的!

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

C++ DLL代码:

代码语言:javascript
复制
// 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代码:

代码语言:javascript
复制
from ctypes import *
import numpy as np
from numpy.ctypeslib import ndpointer

ndDLL = cdll.LoadLibrary("./MyDll.dll")

# Triangle Mesh Structure
class TriangleMesh(Structure):
    _fields_ = [
        ("nbrVertices", c_int),
        ("nbrTriangles", c_int),
        ("vertices", POINTER(c_float)),
        ("triangles",POINTER(c_int))]

# LCSNoduleEx Structure
class ROI(Structure):
    _fields_ = [
        ("xmm", c_double),
        ("ymm", c_double),
        ("zmm", c_double),
        ("diameter", c_double),
        ("level", c_double),
        ("volume", c_double),
        ("threshold", c_double),
        ("isMesh", c_int),
        ("mVol", c_double),
        ("mass", c_double),
        ("meanD", c_double),
        ("dve", c_double),
        ("dla", c_double),
        ("dsa", c_double),
        ("dla3D", c_double),
        ("spike", c_double), 
        ("sphere", c_float),

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

        ("mesh", TriangleMesh)
     ]


def PrintROI(pMem, NumROI):

    for i in range():):
        print("ROI %d"%(i), flush=True)
        print("\tlevel %f"%(pMem[i].level), flush=True)
        print("\tdiameter %f"%(pMem[i].diameter), flush=True)
        print("\tdla3D %f"%(pMem[i].dla3D), flush=True)
        print("\tddla %f"%(pMem[i].dla), flush=True)
        print("\tmeanD %f"%(pMem[i].meanD), flush=True)
        print("\tdai %f"%(pMem[i].dai), flush=True)
        print("\tdve %f"%(pMem[i].dve), flush=True)

        print("\tmass %f"%(pMem[i].mass), flush=True)

        print("\tthreshold %f"%(pMem[i].threshold), flush=True)

        print("\tspiculation %f"%(pMem[i].spike), flush=True)
        print("\tspiculation2 %f"%(pMem[i].sphere), flush=True)

        print("\tvolume %f"%(pMem[i].volume), flush=True)
        print("\tmVol %f"%(pMem[i].mVol), flush=True)
        print("\txmm %f"%(pMem[i].xmm), flush=True)
        print("\tymm %f"%(pMem[i].ymm), flush=True)
        print("\tzmm %f"%(pMem[i].zmm), flush=True)

        print("\tla3D %f, %f, %f, %f, %f, %f"%(pMem[i].la3D[0],
                                                    pMem[i].la3D[1],
                                                    pMem[i].la3D[2],
                                                    pMem[i].la3D[3],
                                                    pMem[i].la3D[4],
                                                    pMem[i].la3D[5]), flush=True)

        print("\tsais %f, %f, %f, %f, %f, %f"%(pMem[i].sais[0],
                                                           pMem[i].sais[1],
                                                           pMem[i].sais[2],
                                                           pMem[i].sais[3],
                                                           pMem[i].sais[4],
                                                           pMem[i].sais[5]), flush=True)

        print("\tLAIS %f, %f, %f, %f, %f, %f"%(pMem[i].lais[0],
                                                            pMem[i].lais[1],
                                                            pMem[i].lais[2],
                                                            pMem[i].lais[3],
                                                            pMem[i].lais[4],
                                                            pMem[i].lais[5]), flush=True)

        print("\tisMesh %d"%(pMem[i].isMesh), flush=True)


        print("\tnbrVertices %d"%(pMem[i].mesh.nbrVertices))
        print("\tnbrTriangles %d"%(pMem[i].mesh.nbrTriangles))


        for j in range(pMem[i].mesh.nbrVertices):
            print("\t\tVertices %d) %f"%(j,pMem[i].mesh.vertices[j]), flush=True)

        for j in range(pMem[i].mesh.nbrTriangles):
            print("\t\tTriangle %d) %d"%(j,pMem[i].mesh.triangles[j]), flush=True)

ndDLL.CreateROI.argtypes  = [POINTER(POINTER(ROI)), POINTER(c_int)]

pMem= POINTER(LCSNoduleEx)()
NumROI = c_int(1)

ndDLL.CreateROI(byref(pMem),byref(NumROI) )


PrintROI(pMem, NumROI.value)
EN

回答 1

Stack Overflow用户

发布于 2018-08-23 07:12:12

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

我不知道哪一个是相关的,因为您的垃圾似乎在一个名为spic的字段中,该字段既没有出现在C++结构中,也没有出现在…的ctype中

首先,你会得到两个乱序的字段:

代码语言:javascript
复制
double threshold;
int isMesh;
double mVol;

代码语言:javascript
复制
("threshold", c_double),
("mVol", c_double),
("isMesh", c_int),

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

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

代码语言:javascript
复制
float lais[6];  
float sais[6];  
float la3D[6];      

代码语言:javascript
复制
("lais", c_double*6),   
("said", c_double*6), 
("la3D", c_double*6),       

float是32位;c_double是64位。lais[0]是由lais[0]lais[1]打包在一起作为double的垃圾double,lais[4]sais[2]sais[3]打包在一起,la3D[4]是超出结构末尾的堆中的64个随机位。如果幸运的话,当你尝试读取它时,你会得到一个段错误,但是如果你不幸运,你就会得到很难调试的垃圾。

对于像这样真正复杂的结构,我通常不相信自己会手动编写ctypes版本,除非犯的错误至少是您的三倍。相反,我编写了一个快速脚本来解析头部(偶尔也会解析文档)并生成Python代码。对于像CoreFoundation和Win32头这样的东西,它们有数以千计的大得离谱的结构,它们都是以非常严格和可靠的风格编写的,我有反复使用的脚本。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51976302

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档