Мне нужно использовать код из LabVIEW
в Python
. Код LabVIEW
используется как DLL
. Итак, я использую библиотеку ctypes
в Python. В одном случае мне нужно передать cluster
s из Python в LabVIEW. У меня проблемы с прохождением кластеров.
Проблема заключается в особом порядке расположения элементов внутри кластера LabVIEW (я знаю, что кластеры строго следуют порядку). Мой кластер имеет значение double
и integer array
. Когда double является первым элементом в кластере, все работает хорошо. Но когда массив установлен в качестве первого элемента и удваивается в качестве второго элемента, все не работает вообще. Я использую LabVIEW 2015 (32-разрядная версия) и Python 3 (32-разрядная версия).
Я подозреваю, что причиной проблемы является ctypes
. Потому что одна и та же DLL работает, как и ожидалось, в C
и в LabVIEW
. Я также попытался использовать DLL в LabVIEW, которая работает нормально.
Я сузил эту проблему до следующего примера. DLL в этом примере имеет 2 функции. Каждая функция использует кластер. Func1
использует cluster1
, то есть array
, за которым следует double
. В то время как Func2
использует cluster
, то есть double
, за которым следует array
.
Обе эти функции получают 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 для func1
Код LabVIEW для func2
Кто-нибудь сталкивался с этой проблемой? Что нужно сделать в этом случае?