struktury w dll - uzycie w LV

Tematy związane z tworzeniem dużych aplikacji. Zaganiednia dotyczące architektury oraz zasad tworzenia optymalnych rozwiązań.
nawiiwan
Posty: 4
Rejestracja: 17 lip 2007 00:00
Lokalizacja: Wrocław

struktury w dll - uzycie w LV

Post autor: nawiiwan »

Witam, mam problem z wywoływaniem funkcji z dllki. Moja funkcja pobiera jako jeden z argumentów wskaźnik do struktury.
Definicja struktury Small i jednocześnie zdefiniowanie typu będącego wskaźnikiem na tę strukturę - SmallPrt:

Kod: Zaznacz cały

 typedef struct Small {
double DoubleNr_1;
signed int IntNr;
double DoubleNr_2;
char CharValue[50];
double DoubleNr_3; } *SmallPtr;
Funkcja wykorzystująca powyższą strukturę (wskaźnik do tej struktury):

Kod: Zaznacz cały

extern "C" __declspec(dllexport) int __stdcall OneSmall(int IntValue_1, SmallPtr SmallValue, int *IntValue_2){
SmallValue->IntNr=-123456789;
SmallValue->DoubleNr_1=123.456;
SmallValue->DoubleNr_2=234.567;
SmallValue->DoubleNr_3=345.678;
strncpy(SmallValue->CharValue, "00 abcDEF
10 abcDEF
20 abcDEF
30 abcDEF
40 abcDEF",50);
return IntValue_1+*IntValue_2; }
DLL-ka: milib.cpp milib.h milib.dll milib.zip - Projekt VC++ spakowany
Wszystko wydaje sie proste, ale ugrzęzłem. Pierwszy problem to Ĺşle zwracana wartość DoubleNr_2 i DoubleNr_3 podczas gdy wartość DoubleNr_1 jest poprawna. Nie rozumiem też dlaczego zwracana wartość z funkcji typu int, która powinna byc sumą IntValue_1+IntValue_2, jest Ĺşle wyświetlona. Jak zrobiłem dll-kę która miała w strukturze int i char[n] to zwracana suma była poprawna. Nie było również problemów ze zwracaniem wartości int w strukturze.
Znalazłem definicje typów int, double. Wyglądają tak samo. W manualu do VC++ http://msdn2.microsoft.com/EN-US/librar ... S.80).aspx signed int, int is 4 bytes, range: –2,147,483,648 to 2,147,483,647 double is 8 bytes, range 1.7E +/- 308 (15 digits), stored as: sign bit, 11-bit exponent, 52-bit mantissa
W opisie dla LV data_manipulation.zip z Data Manipulation.ppt I32 is 32 bits=4 bytes DBL is 8 bytes, stored as: sign bit, 11-bit exp, 52-bit mantissa
VI z kodem: milib_onesmall.vi wygląda tak jak poniżej: Obrazek
Wywołanie dll-ki Obrazek
Obrazek
Obrazek
Obrazek
Obrazek
Wynik uruchomienia jest następujący: Obrazek
Porównując z funkcją w dll-ce (powyżej) widać, że jest cos nie tak.
Drugim problemem na jaki się natknąłem to jak zrobić definicje char[n] gdy n>256 (256 ponieważ Array To Cluster ma ograniczenie do 256 znaków na wyjściu). Do tego jak to póĹşniej przekształcic na string w LV. Znalazłem, że można to zrobić stosujac np U64 zamiast U8, jednak problem pozostaje gdy tych U64 będzie wiecej niż 256 (np. dla char[5000]). Struktura z char[n], n>256:

Kod: Zaznacz cały

typedef struct Large {
double DoubleNr_1;
signed int IntNr;
double DoubleNr_2;
char CharValue[1000];
double DoubleNr_3; } *LargePtr;
Funkcja wykorzystująca powyższą strukturę (wskaĹşnik do tej struktury):

Kod: Zaznacz cały

extern "C" __declspec(dllexport) int __stdcall OneLarge(int IntValue_1, LargePtr LargeValue, int *IntValue_2){
LargeValue->IntNr=-1123456789;
LargeValue->DoubleNr_1=9123.456;
LargeValue->DoubleNr_2=9234.567;
LargeValue->DoubleNr_3=9345.678;
strncpy(LargeValue->CharValue, "000 a-bcde-fghi-jklm-nopq-rstu-vwxy-zABC-DEFG-HIJK-LMNO-PQRS+TUVW-XYZa-bcde-fghi-jklm-nopq-rstu-vwx
100 a-bcde-fghi-jklm-nopq-rstu-vwxy-zABC-DEFG-HIJK-LMNO-PQRS+TUVW-XYZa-bcde-fghi-jklm-nopq-rstu-vwx
200 a-bcde-fghi-jklm-nopq-rstu-vwxy-zABC-DEFG-HIJK-LMNO-PQRS+TUVW-XYZa-bcde-fghi-jklm-nopq-rstu-vwx
300 a-bcde-fghi-jklm-nopq-rstu-vwxy-zABC-DEFG-HIJK-LMNO-PQRS+TUVW-XYZa-bcde-fghi-jklm-nopq-rstu-vwx
400 a-bcde-fghi-jklm-nopq-rstu-vwxy-zABC-DEFG-HIJK-LMNO-PQRS+TUVW-XYZa-bcde-fghi-jklm-nopq-rstu-vwx
500 a-bcde-fghi-jklm-nopq-rstu-vwxy-zABC-DEFG-HIJK-LMNO-PQRS+TUVW-XYZa-bcde-fghi-jklm-nopq-rstu-vwx
600 a-bcde-fghi-jklm-nopq-rstu-vwxy-zABC-DEFG-HIJK-LMNO-PQRS+TUVW-XYZa-bcde-fghi-jklm-nopq-rstu-vwx
700 a-bcde-fghi-jklm-nopq-rstu-vwxy-zABC-DEFG-HIJK-LMNO-PQRS+TUVW-XYZa-bcde-fghi-jklm-nopq-rstu-vwx
800 a-bcde-fghi-jklm-nopq-rstu-vwxy-zABC-DEFG-HIJK-LMNO-PQRS+TUVW-XYZa-bcde-fghi-jklm-nopq-rstu-vwx
900 a-bcde-fghi-jklm-nopq-rstu-vwxy-zABC-DEFG-HIJK-LMNO-PQRS+TUVW-XYZa-bcde-fghi-jklm-nopq-rstu-vwx",1000);
return IntValue_1+*IntValue_2; } 
Następny problem to wywołanie funkcji w dll-ce która przyjmuje jako argument potójny wskaĹşnik, ostatni wskaĹşnik wskazuje na strukturę. Inaczej ujmując jest to wskaĹşnik na tablicę wskaĹşników (tablica wskaĹşników jest podwójnym wskaĹşnikiem). Rozmiar tablicy NIE jest znany przed wywołaniem funkcji dlatego przekazywany jest wskaĹşnik na tablicę a nie na pierwszy element tablicy. Ilość elementów tablicy zwracana jest z funkcji - parametr count. Pamięć na tablicę wskaĹşników oraz struktury na które wskazują wskaĹşniki w tablicy jest alokowana w DLLce.
Funkcja wykorzystująca strukturę Small (potrójny wskaĹşnik do tej struktury):

Kod: Zaznacz cały

extern "C" __declspec(dllexport) int __stdcall FewSmall(int IntValue_1, SmallPtr **SmallValuePtr, int *IntValue_2, int *count){
int i;
SYSTEMTIME SysTime;
SmallPtr *SmallPtrTbl = NULL;

GetSystemTime(&SysTime);
*count=3+(int)SysTime.wMilliseconds/100; // 3...13
 *SmallValuePtr=SmallPtrTbl=(SmallPtr *)calloc(*count + 1, sizeof(SmallPtr));
 for(i = 0; i <*count; i++) {
 SmallPtr SmallValueTbl = (SmallPtr)calloc(1, sizeof(Small));
 SmallValueTbl->IntNr=1000+i;
 SmallValueTbl->DoubleNr_1=123.456+1000*i;
 SmallValueTbl->DoubleNr_2=234.567+10000*i;
 SmallValueTbl->DoubleNr_3=345.678+100000*i;
 sprintf(SmallValueTbl->CharValue, "00 abcDEF
10 abcDEF
20 abcDEF
30 abcDEF
40 abc %02d",i);
 *SmallPtrTbl++=SmallValueTbl;
}
return IntValue_1+*IntValue_2; } 
Próbowałem przekazywać tablice, clustry clustrów. Nic sensownego nie usyskałem. Support NI też nie pomógł. Google było bezradne.
Wiem, że jednym z rozwiazań jest napisanie dll-ki pośredniczącej pomiedzy właściwą dll i LV. Chciałbym jednak tego uniknąć dlatego proszę Was o pomoc.
Zrobiłem przykłady użycia biblioteki w C++ milib_test.exe milib_test.cpp milib_test.zip - Projekt VC++ spakowany
Pozdrawiam, Maciek
PS Obrazki i pliki są z innego serwera, czasami trzeba przeładować stronę aby załadowały się obrazki.
olszus
Posty: 9
Rejestracja: 08 maja 2007 00:00
Lokalizacja: poland

Re: struktury w dll - uzycie w LV

Post autor: olszus »

Problem leży w wyrównywaniu pól struktur przez VC++, trzeba przestawic ta opcje na 1byte, ewentualnie ulozyc optymaliniej pola struktury np.
struct ela
{ double a;
double b;
int c;
}; (double po sobie, 8,8,4)
Opcja ta przestawieniu w menadżerze projektu i opcjach jego kompilacji.
ZbychoZbych
Posty: 12
Rejestracja: 24 lip 2007 00:00

Re: struktury w dll - uzycie w LV

Post autor: ZbychoZbych »

Dokładnie trzeba zmienić: Project->Properties->configuration properties->c/c++->code generation->sruct member alignment na 1byte /zp1, ewentualnie na wieksze jesli nie bedziemy korzystac z charow, lub ich nie wyrownanych do parzystej wartosci tablic. Ja urzywam Visual Studio 2005. Na tej bibliotece program dziala (chyba), ale przekazywanie powinno juz funkcjonowac bezzarzutu.
Pozdrawiam Zbyszek
Zbyszek
nawiiwan
Posty: 4
Rejestracja: 17 lip 2007 00:00
Lokalizacja: Wrocław

Re: struktury w dll - uzycie w LV

Post autor: nawiiwan »

Dzięki za podpowiedzi.

Skompilowalem nowe wersje dllki i exe zgodnie z Waszymi sugestiami. Teraz vi działa bez problemów.
milib_1.dll
milib_1.zip - Projekt VC++, wersja 8bit struktura spakowany

milib_test_1.exe
milib_test_1.zip - Projekt VC++, wersja 8bit struktura spakowany

Pozostają jeszcze zagadnienia char[n] i potrójny wskaźnik. Próbowałem cos wyszukać ale i tak grzęznę.

Proszę o porady.

Pozdrawiam,
Maciek
ODPOWIEDZ