podwójny wskaźnik

0

dostałem dll z labview i tam jest konstrukcja Uint8Array z podwojnym ** w strukturze przekazywanej jako parametr funkcji ,

mam tablice profil001 (w moim kodzie) i chciałbym ja przekazać do funkcji calculate(...) zadeklarowana w labview

#include <cctype>
#include <cstdint>
#include <vector>
#include <cstring>
#include <cstdio>


#define SIZE_PROFILE (16)

uint8_t profil001[SIZE_PROFILE] = 
{
    11,12,13,14,15,16,17,18,19,22,23,24,26,29,33,44
};

typedef struct {
	int32_t dimSize;
	uint8_t elt[1];
} Uint8ArrayBase;

typedef Uint8ArrayBase **Uint8Array;

typedef struct {
     Uint8Array profile;
}Params001;

void calculate(Params001* params)
{
    printf("%d\n",  (*(params->profile))->dimSize );
}


int main()
{
    // alokuje pamiec za pomoca std::vector
    std::vector<uint8_t> data(SIZE_PROFILE+ sizeof(int32_t) ); 

    // rzutuje pamiec na (Uint8ArrayBase)
    Uint8ArrayBase * structPtr = (Uint8ArrayBase *) data.data();    

    // wisuje rozmiar 
    structPtr->dimSize = SIZE_PROFILE;

    // kopiuje dane 
    memcpy(structPtr->elt, profil001, SIZE_PROFILE );

    // struktura z parametrami 
    Params001 params;

    // wpisuje profil   
    params.profile = &structPtr;

    //uruchamiam funkcje 
    calculate(&params);
}
5

Ok, jakie jest pytanie?

0

Jak zaalokować taka zmienną Uint8Array ?
Z tego co widzę to moja metoda działa , ale czy to tak powinno być używane ?

4
Marius.Maximus napisał(a):

Jak zaalokować taka zmienną Uint8Array ?
Z tego co widzę to moja metoda działa , ale czy to tak powinno być używane ?

Co to za dokładnie funkcja, czy jest udokumentowana, a może to jest funkcja napisana pod LabView i masz kod do niej (AFAIK LabView używa C z własnymi bibliotekami)?
Tu nie ma innego sposobu, trzeba zacząć od dokumentacji lub przeanalizować włąściwy kod.

Googlanie znalazłem coś takiego:

Re: Labview created DLL with 2D array

Your doing this pretty wrong!

hROI = (Uint8ArrayBase**) DSNewHandle (sizeof (Uint8ArrayBase));
(*hROI)->dimSizes[0] = 60;
(*hROI)->dimSizes[1] = 30; 
(*hROI)->elt[0] = 0;

This only allocates a memory area that can hold the dimSizes header and a single data element. Don't try to write to (*hROI)->elt[1] ever or you are going to corrupt memory, and if you are lucky it will crash. If you have bad luck nothing seemingly bad will happen but you have destroyed memory contents belonging to something else in LabVIEW, by writing over the end of the allocated buffer.

Instead you need to do this:

int32 dimSizeArr[2];
dimSizeArr[0] = 60;
dimSizeArr[1] = 30;

Uint8Array array = AllocateUint8Array(dimSizeArr);
if (!array)
      err = mFullErr;
else
{
     // do whatever you need to do with the array
     err = DeallocateUint8Array(&array);
}

However it is likely that your function actually creates this array! In that case you would not need to first create it. It really depends if your function somehow initializes this array or simple just references it.

If you happen to have two loops in there, with both autoindexing array output tunnels that get returned into this array parameter at the end you can actually do something like this:

Uint8Array array = NULL;  
double retval = SlantedEdgeSFR4(frequency, y, x, &array);  
if (array)  
{  
    // do something with the data in the array  
    for (i = 0; i < (*array)->dimsSizes[0]; i++)  
    {  
        for (j = 0; j < (*array)->dimSizes[1]; j++)  
        {  
            (*array)->elm[(*array)->dimSizes[1] * i + j] == something;  
        }  
    }  
    err = DeallocateUint8Array(&array);  
}

In case you have already a dizzy head from all the pointers, handles, array subscripts and more, now you know why you prefer to program in LabVIEW rather than in C! :)

And just to show you what the functions most likely look like internally:

Uint8Array AllocateUint8Array(int32 *dimSizeArr)
{
    return (Uint8Array)DSNewHClr(sizeof(int32) * 2 + dimSizeArr[0] * dimSizeArr[1];
}

MgErr __cdecl ResizeUint8Array(Uint8Array *hdlPtr, int32 *dimSizeArr)
{
    return = NumericArrayResize(uB, 2, (UHandle*)hdlPtr, dimSizeArr[0] * dimSizeArr[1];
}

MgErr __cdecl DeAllocateUint8Array(Uint8Array *hdlPtr)
{
    if (hdlPtr)  
    {  
       MgErr err = noErr;  
       if (*hdlPtr)
       {  
           err = DSDisposeHandle((UHandle)*hdlPtr);  
           *hdlPtr = NULL;  
       }  
       return err;  
    }  
    return mgArgErr;  
}

ChatGPT nie jest nawet blisko odpowiedzi.

2

W C++ masz std::vector i std::array
Nie wiem czemu, mam dwie różne implementacje **array.

pierwsza, to masz w pierwszych tab[i][j]
pierwsze i elementów to są wskaźniki na następne tablice, które mają po j elementów.

Lub masz wzór j + j_max * i

Czyli użyjesz std::array będziesz miał taką statyczną tablicę, to za dużo nie ma znaczenia, no chyba że coś tam jeszcze innego jest.

2

Z tego co widzę to moja metoda działa , ale czy to tak powinno być używane ?

W Twoim kodzie nie widzę, nic co by raziło mocno w oczy, z wyjątkiem definicji Params001.

std::vector "trzyma" Twoją pamięć do której masz wskaźnik typu Uint8ArrayBase a potem inicjalizujesz wskaźnik to tego wskaźnika typu Uint8Array zgodnie z jego definicją, także czysto mechanicznie nie widzę tu problemów. Co autor miał na myśli Tworząc Uint8Array jako wskaźnik do wskaźnika to nie wiem, musiałbyś zobaczyć jak jest używany w dostarczonym API. Są dwa typowe zastosowania wskaźnika do wskaźnika - const char **tab co najczęściej oznacza tablicę stringów, lub jako argument w funkcjach by funkcja mogła operować na dokładnie tym samym wskaźniku do którego została zainicjalizowana pamięć a nie na jego kopii.

Jeśli Uint8Array jest używany jako argument w funkcjach to może jego rola to tylko krótki alias bo autorwi nie chciało się stukać w klawiaturę tworząc API a faktycznym typem, kórym powinieneś operować większość czasu to Uint8ArrayBase. Jeżeli tak to miałoby wyglądać to kod powinien wyglądać mniej więcej tak

void calculate(Uint8Array params){}


Uint8ArrayBase * structPtr = (Uint8ArrayBase *) malloc(...);

// .........

calculate(&structPtr);

Ale czy tak to faktycznie miało wyglądać to nie gwarantuje, ciężko zgadnąć co tam autor miał na myśli.

0

Kolega w LabView wyklinał algorytm i udostępnił mi DLL + H możliwe że typy danych są jakoś generowane przez jego narzędzie

Ten kod z mojego pierwszego postu rzeczywiscie dziala , bo udało mi się uruchomić tą biblioteke DLL i wyniki mam poprawne

W oryginalnym H byłą funkcja ktora alokuje Uint8ArrayBase ale kolega uznał że mi nie będzie potrzebna i mi ją wyciął z pliku H

1

No niestety, w C tak jest, że nagłowek jest jak najdalszy od samo-dokumentowania się.

To zabójcze (w tym przypadku) tzw "modele pamieci". W samej bibliotece standardowej, jak w API widzisz wskaźnik, nie wiesz czy
a) jest kopią argumentu
b) jest wskaźnikiem na obszar statyczny (a rzecz nie jest wielowątkowa)
c) jest alokowany przez krewnych malloc i użytkownik API ma to zwolnić
d) modyfikowane sa dane wejsciowe
e) kilka innych

Marius.Maximus napisał(a):

Kolega w LabView wyklinał algorytm i udostępnił mi DLL + H możliwe że typy danych są jakoś generowane przez jego narzędzie

Ten kod z mojego pierwszego postu rzeczywiscie dziala , bo udało mi się uruchomić tą biblioteke DLL i wyniki mam poprawne

Jeśli myslisz, że jest dobrze, to (na gruncie C) prawdopdobnie nie jesteś w pełni poinformowany :)

Pierwsze z brzegu, co sie nasuwa: wycieki pamięci, o jakich nie wiesz, nie udało ci się wywołać błędów od wspólbieżnosci (wątków), bo nie zawsze następują, zbyt mała ilość użyć / zbyt mało agresywnych aby ujawniły się błedy (np od podwójnych zwolnień, użyciu po zwolnieniu i podobne)

Danie dorobku w C bez dokumentacji to duże wykroczenie, to nie Java czy C#

2

@AnyKtokolwiek przeszliśmy ta drogę i na wlasnej skorze przeżyliśmy mase problemow , powoli czasy labview w moich projektach powoli sie kończą ;)
jakiś czas temu zapowiedziałem kolegom ze przyjmuje tyko coś co jestem w stanie skompilować , to zaczęli i wysyłać c+h z ogromną ilosci new/delete , potem im pokazałem std:vector to zaczeli uzywac c++ a niedlugo pewnie przyjdzie czas na shared_ptr i obiekty :)

0

@Marius.Maximus:

aha.

Nie jest dla mnie jasne, co jest WYMOGIEM LabView (jakie konwencje wywołania), sądziłem że te masakry to są stąd

1 użytkowników online, w tym zalogowanych: 0, gości: 1