Функция библиотеки вызовов LabVIEW, выдающая массив строк - PullRequest
1 голос
/ 30 октября 2019

Мне нужно связать код C с LabVIEW, а моей функции C нужно вернуть двумерный массив строк. Я бы не хотел заранее определять размер массива заранее. Итак, я хочу знать, какой формат данных использовать (дескриптор к массиву указателей строки C? Дескриптор к массиву дескрипторов строки?), Как правильно выполнить выделение, и лучше ли использовать параметр массива илитип возврата. Диалог, предусмотренный для Узла функций библиотеки вызовов, поддерживает только массивы числовых типов, поэтому я немного растерялся, как это структурировать.

1 Ответ

2 голосов
/ 31 октября 2019

Вам понадобится справочное руководство по коду LabVIEW , чтобы разобраться в этом.

Вы пишете функцию C, которая будет возвращать 2D-массив строк в LabVIEW. Это означает, что вам нужно возвращать структуру данных LabVIEW и использовать распределитель памяти LabVIEW. Включите «extcode.h» в ваш C-файл (поставляется с LabVIEW). Затем создайте следующий код C:

#include "extcode.h"

struct String2DArrayBlock {
    int32 dimensionSize1;
    int32 dimensionSize2;
    LStrHandle stringArray[1]; // Yes, this is intentional. Do not use LStrHandle* because that syntax changes the memory allocation. Old-school C code. LabVIEW's own C++ code has wrappers for managing this with more type safety. 
};

typedef String2DArrayBlock** String2DArrayHandle;

MgErr GenerateMyStrings(String2DArrayHandle *ptrToHandle) {
    if (!ptrToHandle)
        return mgArgErr; // Gotta pass a location for us to allocate.

    if (*ptrToHandle) {
        // This handle is already allocated. I'm not going to walk you through all the code needed to deallocate.
        return mgArgErr;
    }

    const int32 dimSize1 = ComputeHeight(); // This is your function... whereever your data is coming from.
    const int32 dimSize2 = ComputeWidth(); // Same here. 

    const int32 numberOfElements = dimSize1 * dimSize2;

    if (numberOfElements == 0) {
        return mgNoErr; // Done. NULL means empty array, and the handle is already NULL.
    }

    // DSNewHClr allocates the block and flood fills it with all zeros.
    *ptrToHandle = (String2DArrayHandle)DSNewHClr(sizeof(String2DArrayBlock) + ((numberOfElements - 1) * sizeof(LStrHandle))); // -1 because the sizeof block has 1 element. 
    if (!*ptrToHandle)
        return mFullErr; // Out of memory

    (**ptrToHandle)->dimensionSize1 = dimSize1;
    (**ptrToHandle)->dimensionSize2 = dimSize2;

    LStrHandle *current = (**ptrToHandle)->stringArray;
    for (int32 i = 0; i < numberOfElements; ++i, ++current) {
        std::string myCurrentString = GetMyCurrentString(i); // You write this however you look up the individual strings.
        if (myCurrentString.empty())
            continue; // NULL means empty string
        *current = (LStrHandle)DSNewHClr(sizeof(LStr)); // Allocates a zero-length LStrHandle.
        if (!*current)
            return mFullErr; // The array will be partially filled, but it is in a safe state for early return.
        MgErr err = LStrPrintf(*current, (CStr)"%s", myCurrentString.c_str());
        if (err)
            return err; // The array will be partially filled, but it is in a safe state for early return.
    }

    return mgNoErr;
}

Скомпилируйте свой код с использованием движка LabVIEW (lvrt.dll).

В своем коде G перетащите узел библиотеки вызовов, добавьтепараметр «Адаптировать к типу» и «Указатели на дескрипторы» и связать его с пустым 2D-массивом. И вы сделали.

...