DLL C++

Jeśli masz coś do powiedzenia w sprawie LabVIEW napisz. Tutaj są tematy, których nie można uściślić do innych działów.
Dziech
Posty: 34
Rejestracja: 11 sie 2011 12:19
Wersja środowiska: LabVIEW 2010

DLL C++

Post autor: Dziech »

Dziękuję za dotychczasowy udział w temacie. Mam nowiny i pytanie ; )

po pierwsze - mam funkcję w DLL

Kod: Zaznacz cały

void LV_setVoltages(char fileName[],double vlt[]) {

	
	readDmc(fileName); \\funkcje ze zlinkowanej DLL
	setVoltages(vlt);
	dmcFree();

};
Po zdebuggowaniu w VS i w LV można powiedzieć, że :

1. LV zapodaje dobre argumenty, w formie w jakiej chcę. Po tym, jak dojdą do VS - dzieje się:

a) jeśli vlt = [1,...], to VS widzi adres komórki, a za value widzi =1. Logiczne, bo pointer ma wartość 1.
b) jeśli vlt = [0,...] to VS widzi adres komórki, ale value = 0. O co tutaj chodzi ?

2. Jeśli urządzenie, które steruję jest podłączone, przy funkcji czytania pliku LV się zawiesza na amen, a jeśli urządzenie jest odłączone - program dochodzi do końca, z problemami opisanymi wyżej.

Może LV ma jakieś problemy z FTDI ?
PiDi
Posty: 641
Rejestracja: 31 gru 2010 01:36
Wersja środowiska: LabVIEW 2017
Lokalizacja: Katowice

Re: DLL C++

Post autor: PiDi »

Możemy trochę ogarnąć ten wątek? Bo chyba tylko jeden oczekp jeszcze jako tako nadąża za Tobą :p
1. LV zapodaje dobre argumenty, w formie w jakiej chcę. Po tym, jak dojdą do VS - dzieje się:

a) jeśli vlt = [1,...], to VS widzi adres komórki, a za value widzi =1. Logiczne, bo pointer ma wartość 1.
b) jeśli vlt = [0,...] to VS widzi adres komórki, ale value = 0. O co tutaj chodzi ?
No właśnie, o co chodzi? To w nawiasach to wartości tej tablicy? Te funkcje to są te same, które są w poście datowanym na 17 sie 2011 22:56?
2. Jeśli urządzenie, które steruję jest podłączone, przy funkcji czytania pliku LV się zawiesza na amen, a jeśli urządzenie jest odłączone - program dochodzi do końca, z problemami opisanymi wyżej.
Tzn. LV umiera, tak? Całe środowisko przestaje działać? Gdzieś tu po drodze chyba była mowa o błędnych wskaźnikach i skrobaniu po pamięci, to może być pierwszy potencjalny winowajca.
Może LV ma jakieś problemy z FTDI ?
Co dokładnie z FTDI? To jest po stronie urządzenia, z którym się komunikujesz?

Mógłbyś jakoś sformułować dokładnie problem, który masz w tej chwili? Ja mam naprawdę dobre intencje i chciałbym Ci pomóc, ale strasznie chaotycznie opisujesz wszystko ;)
ObrazekObrazekObrazekObrazek
Dziech
Posty: 34
Rejestracja: 11 sie 2011 12:19
Wersja środowiska: LabVIEW 2010

Re: DLL C++

Post autor: Dziech »

Hej ! : ) Jasne, postaram się odpowiedzieć na pytanie.

vlt, to argument do funkcji, o których mówiłem wcześniej właśnie w tamtym poście. To w nawiasach to wartości, pisałem kropki, bo nie chce mi się pisać 18tu liczb ; ). Po małych zmianach, nazwijmy to labv_plug.DLL:

Kod: Zaznacz cały

ODev* odev_1;  // used for pointer to output device
ODev* odev_2;  // used for pointer to manual feed device
CDev* cdev;    // pointer to controller device

PLUGLABVIEW_API bool readDmc(const char* fileName) // read *dmc file
and initialize devices
{

       bool ret = false;
       auto_ptr<OKODmcData> newdata;
       try { // critical stuff, just exit if it throws
               newdata = auto_ptr<OKODmcData>(new OKODmcData(string(fileName)));
               odev_1 = newdata->createOutput();
               ret = true; }
       catch(...) {
               odev_1 = NULL;
               return(ret); }

       try { // noncritical stuff, forget about it if it throws
               cdev = newdata->createControl(); // throws if no control data available
               odev_2 = new ODFeed(newdata->nControlModes());
               cdev -> attachOutput(odev_1);
               cdev -> attachMeter(odev_2); }
       catch(...) {}
       return(ret);
};

PLUGLABVIEW_API void setVoltages(const double* vlt) // apply voltages
to the output device. length of vlt array is supposed to be >=
device1->signalLength()
{
       if(odev_1){
               odev_1-> set(vlt); }
};

PLUGLABVIEW_API void dmcFree()
{
       delete cdev;
       delete odev_2;
       delete odev_1;
       cdev = NULL;
       odev_2 = NULL;
       odev_1 = NULL;
}

PLUGLABVIEW_API void setZernike(const double* zer) // set zernike
modes amplitudes. length of zer array is supposed to be >=
device2->signalLength()
{
       if(odev_2 && cdev){   // just to ensure devices are properly initialized
               odev_2->set(zer);  // set amplitudes to manual control device
               cdev->sweep();  }  // run one control cycle (read device2, calculate
output signal, apply it to device1)
};

PLUGLABVIEW_API int nChannels()
{
       int ret = 0;
       if(odev_1)
               ret = odev_1->signalLength();
       return(ret);
}

PLUGLABVIEW_API int nModes()
{
       int ret = 0;
       if(odev_2){
               ret = odev_2 -> signalLength();}
       return(ret);
}


BOOL WINAPI DllMain(HINSTANCE hinstDLL,
DWORD     fdwReason,
LPVOID    lpvReserved)
{
   switch (fdwReason)
   {
       case DLL_PROCESS_ATTACH:
           /* Init Code here */
           break;

       case DLL_THREAD_ATTACH:
           /* Thread-specific init code here */
           break;

       case DLL_THREAD_DETACH:
           /* Thread-specific cleanup code here.
           */
           break;

      case DLL_PROCESS_DETACH:
           /* Cleanup code here */
           break;
   }
   /* The return value is used for successful DLL_PROCESS_ATTACH */
       return TRUE;

}
Błędy ze wskaźnikami błędami, ale testowy exek działa z tym DLL... Teraz ja tworzę sobie inne DLL, które używa labv_plug.DLL. Dlaczego ? Dlatego, że jak tworzę, tak jak radził oczekp kilka DLL node'ów, korzystających z funkcji labv_plug.DLL, łączę je łańcuchami - urządzenie nie reaguje, funkcja readDmc nie czyta pliku itd. Powinno - ale nie działa. (Testowy exe działa). Dlatego wpadłem na pomysł, że jak jest kilka DLL i utworzę obiekty w jednym z nodeów, to przechodząc do drugiego, ten DLL jest zamykany i tym samym tracone są obiekty. Dlatego próbowałem napisać jeden DLL z funkcją LV_setVoltages(nazwa pliku, array vlt); żeby mieć jedną DLL node. Z wiadomym skutkiem.

Aczkolwiek na forums ni jakiś gość napisał, że DLL nie undloaduje się do zamknięcia VI, więc możemy śmiało wrócić do metody kilku DLL node'ów i nie korzystać z dwóch DLL, tylko z jednej...

Po podłączeniu wiesza się całe środowisko LV. Nie da się nawet zakończyć zadania. Czip FTDI245R jest po stronie urządzenia, jak wiadomo to interfejs USB. Sterowniki na pewno zainstalowałem dobrze. Wyszukałem całą instrukcję jak to zrobić ; )

ALE ! Dzisiaj np. nie wiesza się. Tym urządzenie nie reaguje. Podejrzewam, że typ argumentów metodą prób i błędów, DLLce przestały się zgadzać argumenty i nic nie przekazuje do funkcji, ale zostawmy to, bo to nie ma znaczenie. Urządzenie nie reaguje.

Kiepsko ! : D Dzięki za chęci : ) Mam nadzieję, że ogarniemy....

D.
Ostatnio zmieniony 31 sie 2011 11:05 przez Dziech, łącznie zmieniany 1 raz.
PiDi
Posty: 641
Rejestracja: 31 gru 2010 01:36
Wersja środowiska: LabVIEW 2017
Lokalizacja: Katowice

Re: DLL C++

Post autor: PiDi »

Umm... Obawiam się, że znów trochę popłynąłeś, albo to ja nie kontaktuję. Bo po tym poście nadal nie wiem, jaki masz w tej chwili konkretny problem, poza tym, że cośtam przepisujesz i cośtam raz samo działa, a raz samo nie działa :D Mógłbyś mi łopatologicznie wyłożyć, o co chodzi?
ObrazekObrazekObrazekObrazek
oczekp
Posty: 161
Rejestracja: 22 lis 2009 15:12
Wersja środowiska: LabVIEW 2010

DLL C++

Post autor: oczekp »

Heh, PiDi mam to samo uczucie;)
Aczkolwiek na forums ni jakiś gość napisał, że DLL nie undloaduje się do zamknięcia VI, więc możemy śmiało wrócić do metody kilku DLL node'ów i nie korzystać z dwóch DLL, tylko z jednej...
A to jest prawda co ten Gość napisał:) Kilka razy nawet dostałem od LV po uszach, bo próbowałem majstrować przy załadowanym DLL podczas pracy VI.

A próbowałeś, np. połączyć się z urządzeniem za pomocą programu napisanego w c, bez korzystania z LV?
Posprawdzać ten swój kod na C i będziesz miał pewność, że to w LV coś siada, a nie w kodzie.

Patrząc na kod, który zamieściłeś wszystko wygląda okej. Ale ciężko coś więcej powiedzieć nie mając pojęcia co to za klasa ODEV.
Próbowałeś uruchomić wywalając te auto_ptr i dając inne wskaźniki?
a) jeśli vlt = [1,...], to VS widzi adres komórki, a za value widzi =1. Logiczne, bo pointer ma wartość 1.
b) jeśli vlt = [0,...] to VS widzi adres komórki, ale value = 0. O co tutaj chodzi ?
Jaki pointer? I jakie 1?:)
2. Jeśli urządzenie, które steruję jest podłączone, przy funkcji czytania pliku LV się zawiesza na amen, a jeśli urządzenie jest odłączone - program dochodzi do końca, z problemami opisanymi wyżej.
Nie wiem, może etapami posprawdzaj na czym dokładnie siada. Po kolei sobie uruchamiaj fragmenty kodu i dojdziesz czy to siada LV czy coś w kodzie walnięte. Często LV korzystające z DLLki się wiesza, jak się porobi jakieś cyrki ostre w pamięci.
Dziech
Posty: 34
Rejestracja: 11 sie 2011 12:19
Wersja środowiska: LabVIEW 2010

Re: DLL C++

Post autor: Dziech »

oczekp pisze:Heh, PiDi mam to samo uczucie;)
Aczkolwiek na forums ni jakiś gość napisał, że DLL nie undloaduje się do zamknięcia VI, więc możemy śmiało wrócić do metody kilku DLL node'ów i nie korzystać z dwóch DLL, tylko z jednej...
A to jest prawda co ten Gość napisał:) Kilka razy nawet dostałem od LV po uszach, bo próbowałem majstrować przy załadowanym DLL podczas pracy VI.
Ha, programista wpakował wszystko do jednej funkcji, żebym miał jedną DLL node i działa. Pomijając fakt, że nawet on przyznał, że do DLL z FTDI wszystko gra, a potem coś się dzieje. Nie mamy dostępu do tego kodu, więc nie wiadomo co. Wiem tylko, że czasem jak się kompiluje to działa, a czasem nie. Pomaga też odpięcie urządzenia i wsadzenie go z powrotem. Więc problemem również było to, że miałem kilka DLL node. W jakiś sposób VI musiał zamykać, ALBO DLL sam jakoś odnosząc się do innego DLL unloadował obiekty z pamięci. Nie mam pojęcia !
oczekp pisze:Jaki pointer? I jakie 1?:)
Jak przekazujesz array w C++ do funkcji, to w funkcji widziany jest tylko wskaźnik do tej tablicy. A wielkość wskaźnika to 1 bit tak ? Może się mylę ; ) Ale tak twierdzą programiści :D Dlatego, czy LV chce w argumentach funkcji (double vlt[]) czy (double * vlt) to powinno być to samo.
oczekp pisze:Nie wiem, może etapami posprawdzaj na czym dokładnie siada. Po kolei sobie uruchamiaj fragmenty kodu i dojdziesz czy to siada LV czy coś w kodzie walnięte. Często LV korzystające z DLLki się wiesza, jak się porobi jakieś cyrki ostre w pamięci.
No właśnie wyszło, że to wina FTDI. Nie wiadomo co.


A teraz z kolei inny problem ! : D Numeracja tabeli. Wysyłam z LV array np. [1,1,0,0...0] a urządzenie czyta sobie [0,1,1,0,0...,0]. Da się to jakoś zmienić ?
Dziech
Posty: 34
Rejestracja: 11 sie 2011 12:19
Wersja środowiska: LabVIEW 2010

Re: DLL C++

Post autor: Dziech »

Poprzednie pytanie jest nieważne. Mapping kanałów jest z pliku i wszystko się jednak zgadza.

Ale nasunęło mi się pewne pytanie. Jak mam jakąś tablicę, to szare elementy są nieinicjalizowane. Nie wiadomo co pod nimi jest tak ? A ja chcę tak - czytam wielkość tablicy, i robi mi się tablica z np. zerami. Initialize Array.vi może byłoby przydatne, ale ja chcę przy każdym odpaleniu kontrolować np. parę elementów, a te które nie określę, mają być zero. Na ten moment mam coś takiego.
Załączniki
układ
układ
PiDi
Posty: 641
Rejestracja: 31 gru 2010 01:36
Wersja środowiska: LabVIEW 2017
Lokalizacja: Katowice

Re: DLL C++

Post autor: PiDi »

Szare elementy są niezainicjalizowane = nie istnieją. To tak, jakbyś sobie zrobił vector (STL-owy) w C++ na 5 elementów, czyli nie ma już 6, 7, 8 i próba dostania się do nich kończy się błędem. W przypadku zwykłej tablicy rodem z C problem polega na tym, co już wcześniej zauważyłeś - tablica jest w zasadzie wskaźnikiem na swój pierwszy element, co oznacza, że można z nim wyjechać poza tę tablicę. Piszę to w kontekście tego, że gdzieś tam cały czas lata podejrzenie o jeżdżenie po pamięci, po której nie powinieneś pisać.
Jeśli chodzi o Initialize Array - zainicjalizuj całą tablicę zerami, a potem podmień tylko te elementy, które potrzebujesz.

Tak mnie jeszcze naszło, z tymi twoimi "dziwnymi" wartościami z tablic przekazywanych do funkcji:

Kod: Zaznacz cały

setVoltages(const double* vlt)
Trochę przyrdzewiałem ostantio z C, ale jak masz tak zdeklarowaną funkcję, to przypadkiem nie jest tak, że nie możesz zmieniać wartości tego wskaźnika w niej? Czyli jak podasz tablicę do tej funkcji, to możesz dostać się tylko do pierwszego elementu, ale nie możesz tego wskaźnika użyć do iterowania po niej?
ObrazekObrazekObrazekObrazek
Dziech
Posty: 34
Rejestracja: 11 sie 2011 12:19
Wersja środowiska: LabVIEW 2010

DLL C++

Post autor: Dziech »

Mogę, jeśli używam potem

Kod: Zaznacz cały

vlt = new double[SIZE]
Ale i tak, po to jest const - nie jest zmieniana wartość w środku funkcji. Zresztą - to działa : )

Podmienić VI'em, który się nazywa array subset ?

I jeszcze jedno - jednak poprzednie pytanie istnieje dalej... Da się zmienić indeksowanie tablicy ? Chodzi o to, że

Kod: Zaznacz cały

Mapping :
vlt[0] - kanałUrządzenia[19]
vlt[1] - kanałUrządzenia[13]
Niby array'e są indeksowane od 0, tak jak w C++, ale rzecz się dzieje taka, że Mapping wychodzi taki :

Kod: Zaznacz cały

Mapping z LV
vlt[0] - kanałUrządzenia[20]
vlt[1] - kanałUrządzenia[14]
Teraz jak sobie to rozpisałem, to chyba problem jest raczej w kodzie a nie w LV... Ale mimo wszystko - da się ?
Dziech
Posty: 34
Rejestracja: 11 sie 2011 12:19
Wersja środowiska: LabVIEW 2010

Re: DLL C++

Post autor: Dziech »

Ok, ogarnąłem. Na moje oko dobrze. Indicatory się zgadzają. Teraz tylko co z indeksowaniem. Programista mówi, że to nie możliwe : D

Acha - zmiana indeksowania nic nie da, bo mapping nie jest liniowy... Damn.

Dobra, generalnie działa jak odjąłem 1 od każdych kanałów w pliku konfiguracyjnym, ale to nie powinno być rozwiązaniem. LabVIEW coś kopie z indeksowaniem. Wiecie może jak dokładnie LV przekazuje array do funkcji ? Może tam indeksuje od 1 ? A może jakimś cudem LV dodaje sobie przy przetwarzaniu pliku ? Plik jest napisany w XML.
Załączniki
Układ poprawiony
Układ poprawiony
Ostatnio zmieniony 01 wrz 2011 15:14 przez Dziech, łącznie zmieniany 2 razy.
Dziech
Posty: 34
Rejestracja: 11 sie 2011 12:19
Wersja środowiska: LabVIEW 2010

DLL C++

Post autor: Dziech »

Hej : )

Z tym dodawaniem +1 trochę się zapędziłem - urządzenie numeruje inaczej niż w kodzie, więc to nieważne. Mój błąd. Jest dobrze i wszystko działa.

wygląda, że rozwiązaniem problemu było wpakowanie wszystkich funkcji do jednego DLL node'a. Mimo tego, że LV podobno nie zamyka DLL po załadowaniu do zamknięcia VI, to musi jakoś po przejściu do drugiego DLL node'a, albo próbować pisać w pamięci już zajętej a potrzebnej do wykonania następnego DLL node'a, albo faktycznie zamyka DLL : )

pozdro !

Dziękuję za wszelaką pomoc, trochę mnie tu nauczyliście : D
Dziech
Posty: 34
Rejestracja: 11 sie 2011 12:19
Wersja środowiska: LabVIEW 2010

Re: DLL C++

Post autor: Dziech »

No to może napiszę co wyniknęło - dla potomnych.

Dwie kwestie ( po dzisiejszym debuggowaniu do samych DLLek z FTDI ) :

1. W pewnym miejscu było takie oto działanie :

for (... )

x = i*g*f(z); /w skrócie w celu demonstracji

Otóż okazało się, że to działanie wykonywane przez console application wykonuje się w sposób taki : najpierw f(x), a potem wynik mnożony przez resztę.

Natomiast to samo odpalone przez LV, robi się tak, że za pierwszym przebiegiem fora faktycznie f(x) jest wykonywane, ale potem w następnych, zupełnie plącze się porządek tego działania i wychodzi kasza, albo 0.

Rozwiązaniem jest dopisanie linijki wyżej d = f(x), a w działaniu użycie d. Kuriozum : )

2. Wcześniej używałem kilka funkcji, ale z tej samej DLL. Czyli kilka DLL Node, ale otwierających jedną DLL. Zapewne dlatego była kaszana w pamięci. Zmieniłem na jedną funkcję w jednym DLL -> jeden DLL node i śmiga.

Dziękuję wszystkim zabierającym głos. Dzisiaj - działa : D

D.
Ostatnio zmieniony 20 wrz 2011 22:02 przez Dziech, łącznie zmieniany 1 raz.
ODPOWIEDZ