Python ctypes无法与结构一起使用

时间:2019-07-09 09:25:15

标签: python c dll ctypes

我需要使用LabVIEWPython的一些代码。 LabVIEW代码用作DLL。因此,我在Python中使用ctypes库。在一种情况下,我需要将cluster从Python传递到LabVIEW。我在传递群集时遇到问题。

问题出在LabVIEW群集中元素的特定排序(我知道群集严格遵循排序)。我的集群具有一个double值和一个integer array。当double是群集中的第一个元素时,说明一切正常。但是,当将数组设置为第一个元素,并将其设置为第二个元素时,则根本不起作用。我正在使用LabVIEW 2015(32位)和Python 3(32位)。

我怀疑是ctypes引起问题的原因。因为,同一DLL在CLabVIEW中按预期工作。我还尝试了在LabVIEW中使用DLL的效果很好。

我已将此问题缩小为以下示例。本示例中的DLL具有2个功能。每个功能使用一个群集。 Func1使用cluster1,后跟arraydoubleFunc2使用cluster,其后跟doublearray。 这两个函数都接收一个cluster作为输入,而只是返回double值(来自输入集群)作为输出。

在头文件中查找这些信息。

typedef struct {
    int32_t dimSize;
    uint64_t elt[1];
} Uint64ArrayBase;
typedef Uint64ArrayBase **Uint64Array;
typedef struct {
    double Double;
    Uint64Array _1DArray;
} Cluster;
typedef struct {
    Uint64Array _1DArray;
    double Double;
} Cluster1;

/*!
 * Func2
 */
double __cdecl Func2(Cluster *Double1DArrayCluster);
/*!
 * Func1
 */
double __cdecl Func1(Cluster1 *_1DArrayDoubleCluster);

MgErr __cdecl LVDLLStatus(char *errStr, int errStrLen, void *module);

/*
* Memory Allocation/Resize/Deallocation APIs for type 'Uint64Array'
*/
Uint64Array __cdecl AllocateUint64Array (int32 elmtCount);
MgErr __cdecl ResizeUint64Array (Uint64Array *hdlPtr, int32 elmtCount);
MgErr __cdecl DeAllocateUint64Array (Uint64Array *hdlPtr);

这是我的python代码。

from ctypes import *

lib = cdll.LoadLibrary("DLL.dll")
dbl = 45.54
elt_count = 5

class Uint64ArrayBase(Structure):
    _fields_ = [
        ("dimSize", c_int32),
        ("elt", c_uint64 * elt_count)
    ]

class Cluster(Structure):
    _fields_ = [
        ("Double", c_double),
        ("_1DArray", POINTER(POINTER(Uint64ArrayBase)))
    ]

class Cluster1(Structure):
    _fields_ = [
        ("_1DArray", POINTER(POINTER(Uint64ArrayBase))),
        ("Double", c_double)
    ]

Uint64Array = POINTER(POINTER(Uint64ArrayBase))

# Use the given API to allocate array
lib.AllocateUint64Array.restype = Uint64Array
lib.AllocateUint64Array.argtypes = [c_int32]
uintarr_h = lib.AllocateUint64Array(c_int32(elt_count))

# Populate the elts of the array
for i in range(elt_count):
    uintarr_h.contents.contents.elt[i] = c_uint64(i)

# Create cluster instances
dbl_arr_cluster = Cluster(c_double(dbl), uintarr_h)
arr_dbl_cluster = Cluster1(uintarr_h, c_double(dbl))

# Print the array for Debugging
print("Array from arr_dbl_cluster:", end=" ")
for i in range(arr_dbl_cluster._1DArray.contents.contents.dimSize):
    print(arr_dbl_cluster._1DArray.contents.contents.elt[i], end=", ")
print()

print("Array from dbl_arr_cluster:", end=" ")
for i in range(dbl_arr_cluster._1DArray.contents.contents.dimSize):
    print(dbl_arr_cluster._1DArray.contents.contents.elt[i], end=", ")
print()

print("Double from arr_dbl_cluster:", arr_dbl_cluster.Double)
print("Double from dbl_arr_cluster:", dbl_arr_cluster.Double)

# Test the funcs
lib.Func1.restype = c_double
lib.Func1.argtypes = [POINTER(Cluster1)]
lib.Func2.restype = c_double
lib.Func2.argtypes = [POINTER(Cluster)]

print()

result = lib.Func1(byref(arr_dbl_cluster))
print("Double output from DLL function cluster{Array, DBL}:", result)
result_1 = lib.Func2(byref(dbl_arr_cluster))
print("Double output from DLL function cluster{DBL, Array}:", result_1)

还有C代码。

#include<stdio.h>
#include "DLL.h"

int main() {
    double dbl = 45.54, result, result1;
    int32 eltCount = 5, i;

    // Use the API to allocate array
    Uint64Array uia = AllocateUint64Array(eltCount);

    // Populate the elts of the array
    for (i = 0; i < (*uia)->dimSize; i++) {
        (*uia)->elt[i] = (int)i;
    }

    // Create cluster instances
    Cluster cluster = { dbl, uia };
    Cluster1 cluster1 = { uia, dbl };

    // Print for Debugging
    printf("\nArray from cluster1{Array, DBL}: ");
    for (i = 0; i < (*cluster1._1DArray)->dimSize; i++) {
        printf("%llu, ", (*cluster1._1DArray)->elt[i]);
    }
    printf("\nArray from cluster{DBL, Array}: ");
    for (i = 0; i < (*cluster._1DArray)->dimSize; i++) {
        printf("%llu, ", (*cluster._1DArray)->elt[i]);
    }

    printf("\nDouble from cluster1{Array, DBL}: %lf", cluster1.Double);
    printf("\nDouble from cluster{DBL, Array}: %lf", cluster.Double);

    // Test the funcs
    result = Func1(&cluster1);
    result1 = Func2(&cluster);
    printf("\n\nDouble output from DLL function cluster1{Array, DBL}: %lf", result);
    printf("\nDouble output from DLL function cluster{DBL, Array}: %lf", result1);

    return 0;
}

以下是Python的预期输出。这两个函数必须已返回45.54作为输出。

c:/Users/samkm/Desktop/DLL Demo/test.py
Array from arr_dbl_cluster: 0, 1, 2, 3, 4,
Array from dbl_arr_cluster: 0, 1, 2, 3, 4,
Double from arr_dbl_cluster: 45.54
Double from dbl_arr_cluster: 45.54

Double output from DLL function cluster{Array, DBL}: -2.106485661434095e-37  # int(...) -> 0
Double output from DLL function cluster{DBL, Array}: 45.54

C代码将返回预期的输出。

Array from cluster1{Array, DBL}: 0, 1, 2, 3, 4,
Array from cluster{DBL, Array}: 0, 1, 2, 3, 4,
Double from cluster1{Array, DBL}: 45.540000
Double from cluster{DBL, Array}: 45.540000

Double output from DLL function cluster1{Array, DBL}: 45.540000
Double output from DLL function cluster{DBL, Array}: 45.540000

LabVIEW code for Func1 用于func1的LabVIEW代码

LabVIEW code for Func2 用于func2的LabVIEW代码

有人遇到这个问题吗?在这种情况下应该怎么办?

0 个答案:

没有答案