DLL C++
DLL C++
Witam,
Mam gotową bibliotekę DLL. Potrzebuję dostać się do konstruktora, ale labview nie widzi klas cpp niestety. Wyczytałem gdzieś, że można zrobić "wrapper" z cpp do c. Tylko nie za bardzo się na tym znam i nigdy tego nie robiłem. Może na forum jest ktoś po takim zabiegu i by się wypowiedział jak to zrobić ? : > Podobny wątek powinienem wrzucić chyba na jakieś forum cpp - skopiuję odpowiedź jak dostanę - dla potomnych : )
pozdrawiam,
D
Mam gotową bibliotekę DLL. Potrzebuję dostać się do konstruktora, ale labview nie widzi klas cpp niestety. Wyczytałem gdzieś, że można zrobić "wrapper" z cpp do c. Tylko nie za bardzo się na tym znam i nigdy tego nie robiłem. Może na forum jest ktoś po takim zabiegu i by się wypowiedział jak to zrobić ? : > Podobny wątek powinienem wrzucić chyba na jakieś forum cpp - skopiuję odpowiedź jak dostanę - dla potomnych : )
pozdrawiam,
D
DLL C++
Hej, tu masz bardzo dobry link do tego jak takiego wrappera utworzyć:
http://labviewwiki.org/DLL/shared_library
Cytując:
Jak wiadomo w c++ struktura to też jest klasa, zatem, aby utworzyć klasy nieprzezroczyste(niewidoczne), należy po prostu typedefingować (przypisać nazwę alternatywną) klasę do struktury o tej samej nazwie.
A następnie trzeba by wywoływały się funkcje w C zamiast C++. Dokonuje się tego przez dyrektywę extern "C".
Postaram się zaraz utworzyć jakiś prosty przykładzik i wrzucić go tu.
http://labviewwiki.org/DLL/shared_library
Cytując:
Jak wiadomo w c++ struktura to też jest klasa, zatem, aby utworzyć klasy nieprzezroczyste(niewidoczne), należy po prostu typedefingować (przypisać nazwę alternatywną) klasę do struktury o tej samej nazwie.
A następnie trzeba by wywoływały się funkcje w C zamiast C++. Dokonuje się tego przez dyrektywę extern "C".
Postaram się zaraz utworzyć jakiś prosty przykładzik i wrzucić go tu.
Re: DLL C++
Super ! : ) Dziękuję za link. Przeszukałem Internet, ale nie trafiłem na tą stronę. Jak zrobię swoje to też postaram się coś tutaj wklepać : )
Dzięki,
D. : )
Dzięki,
D. : )
Re: DLL C++
Zgodnie z obietnicą podaje przykład, może się komuś przyda.
Załóżmy, że mamy do dyspozycji klasę punkt zdefiniowaną w pliku punkt.h
o takiej budowie:
oraz plik punkt.cpp :
Załóżmy, że chcemy skorzystać sobie z klas napisanych w C++ i utworzyć plik dll do wywoływania różnych funkcji danej klasy w LabVIEW. Jak wiadomo w LV można wywoływać jedynie DLL napisane w czystym C, zatem należy utworzyć opakowanie (wrapper), które "przetłumaczy" klasę w C++ na zwykłe wywołania funkcji w C. Dokładniej oznacza to, że musimy napisać jakiś kod w C, który LabVIEW zrozumie i pośrednio wywoła żądaną klasę w C ++.
Aby tego dokonać należy napisać specjalne opakowanie (wrapper). Jak wiadomo w C++ struktura jest klasą, zatem podczas deklarowania w nagłówku wrappera można napisać coś takiego:
powodując tym samym, że klasa będzie nieprzezroczysta dla naszego wrappera.
Następnie tworzymy funkcje, które będziemy chcieli sobie wywoływać w LabVIEW, a przed całością dajemy specyfikator extern "C" . Przykładowo nagłówek takiego wrappera może wyglądać tak:
Zaś same funkcje w pliku głównym:
Mając wykonany taki dll możemy zabrać się za wstawienie go do LabVIEW, przykład obrazu w załączniku.
Ogólnie polecam przeczytanie strony co wcześniej została podana i jeszcze tej:
http://forums.devx.com/showthread.php?t=170263
Tekst pisałem i tłumaczyłem na szybko więc może mieć trochę błędów.
W załączniku wrzucam przykład takiej biblioteki dll -> punkt.dll
nagłówek wrappera dll.h
plik wrappera dllmain.cpp
nagłówek klasy punkt.h
plik klasy punkt.cpp
oraz przykładowe vi, które korzysta z napisanego dlla -> punkt.vi
Załóżmy, że mamy do dyspozycji klasę punkt zdefiniowaną w pliku punkt.h
o takiej budowie:
Kod: Zaznacz cały
class punkt
{
public:
punkt(int,int); //konstruktor
virtual ~punkt(); //destruktor
void przesun(int,int); //funkcja przesuwająca punkt x,y o zadaną wartość
void pokaz(int*,int*); //wyświetla aktualne wartości x,y
private:
int x,y; //współrzędne punktu x,y
};
Kod: Zaznacz cały
#include "punkt.h"
#include <windows.h>
punkt::punkt(int a, int b)
{
x=a;
y=b;
}
punkt::~punkt()
{
//destruktor
}
void punkt::przesun(int a, int b)
{
x+=a;
y+=b;
}
void punkt::pokaz(int* a,int* b)
{
*a=x;
*b=y;
}
Aby tego dokonać należy napisać specjalne opakowanie (wrapper). Jak wiadomo w C++ struktura jest klasą, zatem podczas deklarowania w nagłówku wrappera można napisać coś takiego:
Kod: Zaznacz cały
typedef struct punkt punkt;
Następnie tworzymy funkcje, które będziemy chcieli sobie wywoływać w LabVIEW, a przed całością dajemy specyfikator extern "C" . Przykładowo nagłówek takiego wrappera może wyglądać tak:
Kod: Zaznacz cały
]#ifndef _DLL_H_
#define _DLL_H_
#if BUILDING_DLL
# define DLLIMPORT __declspec (dllexport)
#else /* Not BUILDING_DLL */
# define DLLIMPORT __declspec (dllimport)
#endif /* Not BUILDING_DLL */
#ifdef __cplusplus
extern "C" { /* using a C++ compiler */
#endif
typedef struct punkt punkt; /* sprawia, że klasa jest nieprzezroczysta dla wrappera */
DLLIMPORT punkt* konstruktor(int a, int b);
DLLIMPORT void przesun_xy(punkt* LV_ref, int a, int b);
DLLIMPORT void pokaz_xy(punkt* LV_ref, int* a, int* b);
DLLIMPORT void destruktor(punkt* LV_ref);
#ifdef __cplusplus
}
#endif
#endif /* _DLL_H_ */
Kod: Zaznacz cały
DLLIMPORT punkt* konstruktor(int a, int b)
{
return new punkt(a,b);
}
DLLIMPORT void przesun_xy(punkt* LV_ref, int a, int b)
{
LV_ref->przesun(a,b);
}
DLLIMPORT void pokaz_xy(punkt* LV_ref, int* a, int* b)
{
LV_ref->pokaz(a,b);
}
DLLIMPORT void destruktor(punkt* LV_ref)
{
delete LV_ref;
}
Ogólnie polecam przeczytanie strony co wcześniej została podana i jeszcze tej:
http://forums.devx.com/showthread.php?t=170263
Tekst pisałem i tłumaczyłem na szybko więc może mieć trochę błędów.
W załączniku wrzucam przykład takiej biblioteki dll -> punkt.dll
nagłówek wrappera dll.h
plik wrappera dllmain.cpp
nagłówek klasy punkt.h
plik klasy punkt.cpp
oraz przykładowe vi, które korzysta z napisanego dlla -> punkt.vi
- Załączniki
-
- punkt.zip
- (25.97 KiB) Pobrany 277 razy
Ostatnio zmieniony 20 sie 2011 20:17 przez oczekp, łącznie zmieniany 1 raz.
DLL C++
Hm, a jeśli mam coś takiego w pliku nagłówkowym :
Poza tym, że moje umiejętności cpp trochę zardzewiały i nie umiem dojść co znaczy ta składnia ; > to nie znalazłem jak można to zmienić. Trochę ciężko się pracuje, jak się nie zna do końca całego kodu : >
EDIT:
A jeszcze tak - może się to komuś przyda - jeśli chcę użyć w lv tylko niektórych funkcji, bo nie potrzebnie przerabiam taką ilość kodu! Muszę umieścić je w extern C, a resztę wywalić poza ? Przepraszam jeśli gdzieś jest odpowiedź : >
D.
Kod: Zaznacz cały
void virtual apply() = 0;
Poza tym, że moje umiejętności cpp trochę zardzewiały i nie umiem dojść co znaczy ta składnia ; > to nie znalazłem jak można to zmienić. Trochę ciężko się pracuje, jak się nie zna do końca całego kodu : >
EDIT:
A jeszcze tak - może się to komuś przyda - jeśli chcę użyć w lv tylko niektórych funkcji, bo nie potrzebnie przerabiam taką ilość kodu! Muszę umieścić je w extern C, a resztę wywalić poza ? Przepraszam jeśli gdzieś jest odpowiedź : >
D.
Ostatnio zmieniony 16 sie 2011 12:01 przez Dziech, łącznie zmieniany 1 raz.
Re: DLL C++
W extern C tworzysz sobie tylko te funkcje, które chcesz sobie wyłuskać z klasy, to znaczy, tylko to co chcesz, resztę po prostu zostawiasz w spokoju:)
void virtual apply() = 0; jest to czysto wirtualna funkcja składowa zdefiniowana w klasie abstrakcyjnej. Więcej, np. tu:
http://www.lanform.com.pl/cpptxt/l36.txt
Zazwyczaj klasy abstrakcyjne to klasy bazowe, w linku co przesłałem wcześniej jest przykład odwoływania się do funkcji wirtualnych w klasach dziedziczonych.
void virtual apply() = 0; jest to czysto wirtualna funkcja składowa zdefiniowana w klasie abstrakcyjnej. Więcej, np. tu:
http://www.lanform.com.pl/cpptxt/l36.txt
Zazwyczaj klasy abstrakcyjne to klasy bazowe, w linku co przesłałem wcześniej jest przykład odwoływania się do funkcji wirtualnych w klasach dziedziczonych.
Re: DLL C++
Witam,
dziękuję za pomoc - działa DLL, ale mam problem z powiązaniem do Labview. Chodzi o to, że mam taki układ - prawdopodobnie można to jakoś zdesignować inaczej, żeby działało, ale nie mam pojęcia jak.
Chodzi o to, że przy danych case'ach nie chcę wywoływać niektórych funkcji DLL. Trzeba osobne DLL stworzyć, czy może wsadzić DLL do każdego case'a ? Nie da się pozostawić otwartego node'a.
D.
P.S. Po dodaniu default if unwired otrzymuję błąd nr 12 z DLL node'a
Possible reason(s):
LabVIEW: Some system capacity necessary for operation is not enabled.
dziękuję za pomoc - działa DLL, ale mam problem z powiązaniem do Labview. Chodzi o to, że mam taki układ - prawdopodobnie można to jakoś zdesignować inaczej, żeby działało, ale nie mam pojęcia jak.
Chodzi o to, że przy danych case'ach nie chcę wywoływać niektórych funkcji DLL. Trzeba osobne DLL stworzyć, czy może wsadzić DLL do każdego case'a ? Nie da się pozostawić otwartego node'a.
D.
P.S. Po dodaniu default if unwired otrzymuję błąd nr 12 z DLL node'a
Possible reason(s):
LabVIEW: Some system capacity necessary for operation is not enabled.
Ostatnio zmieniony 17 sie 2011 15:05 przez Dziech, łącznie zmieniany 2 razy.
Re: DLL C++
Myślałem, że to pomoże, ale teraz każda DLL node daje ten sam błąd. Poza tym, jak usunąłem całą treść funkcji, to wyskakuje ten sam błąd. Więc to raczej nie wina kodu.
P.S Nie - nie kompilowałem DLL dla 64 bit.
P.S Nie - nie kompilowałem DLL dla 64 bit.
Ostatnio zmieniony 17 sie 2011 21:26 przez Dziech, łącznie zmieniany 1 raz.
Re: DLL C++
ciężko tak powiedzieć na pierwszy rzut oka. Najlepiej jakbyś mógł wrzucić cały kod to się wtedy szybciej dojdzie, gdzie jest błąd.
Z pierwszych uwag, to na pewno jak przesyłasz tablicę o n elementach to zwyczajem w programowaniu c jest przesłanie rozmiaru tablicy. Bo za pewne jedziesz w dll jakimś forem.
(To są te same dll i tylko odwołujesz się w nich do innej funkcji? Czy tej samej?)
Ja obstawiam na 100 coś z dll-em, bo drugi załącznik wygląda okej.
Co do pierwszego to muszą być podpięte wszystkie wejścia. Nie wiem dokładnie co tam się dzieje wewnątrz dll-a, ale zawsze możesz podpiąć pustą tablicę jak nie będziesz korzystać, w kodzie c++ sobie sprawdzić czy pusta i wtedy nie robić, co tam byś chciał, albo zrobić jeszcze jakieś wejście typu boolean i w zależności od true czy false wywoływać inną funkcją, bądź jeszcze jakieś inne kombinacje. W każdym bądź razie, jeżeli w definicji funkcji jest, że trzeba podpiąć wszystkie, to muszą być:)
Ja bym na Twoim miejscu jednak zrobił to tak, że dla każdego case dałbym tego samego dlla, z tym, że dla każdego stanu wywoływał odpowiednią funkcję. No chyba, że są jakieś fajniejsze i mądrzejsze rozwiązania.
PS> Czyli używasz LV 32bitowe z 32 bitowymi dllkami?:)
Z pierwszych uwag, to na pewno jak przesyłasz tablicę o n elementach to zwyczajem w programowaniu c jest przesłanie rozmiaru tablicy. Bo za pewne jedziesz w dll jakimś forem.
(To są te same dll i tylko odwołujesz się w nich do innej funkcji? Czy tej samej?)
Ja obstawiam na 100 coś z dll-em, bo drugi załącznik wygląda okej.
Co do pierwszego to muszą być podpięte wszystkie wejścia. Nie wiem dokładnie co tam się dzieje wewnątrz dll-a, ale zawsze możesz podpiąć pustą tablicę jak nie będziesz korzystać, w kodzie c++ sobie sprawdzić czy pusta i wtedy nie robić, co tam byś chciał, albo zrobić jeszcze jakieś wejście typu boolean i w zależności od true czy false wywoływać inną funkcją, bądź jeszcze jakieś inne kombinacje. W każdym bądź razie, jeżeli w definicji funkcji jest, że trzeba podpiąć wszystkie, to muszą być:)
Ja bym na Twoim miejscu jednak zrobił to tak, że dla każdego case dałbym tego samego dlla, z tym, że dla każdego stanu wywoływał odpowiednią funkcję. No chyba, że są jakieś fajniejsze i mądrzejsze rozwiązania.

PS> Czyli używasz LV 32bitowe z 32 bitowymi dllkami?:)
Re: DLL C++
Dokładnie tak zrobiłem. Wywołuję w każdym dll node inne funkcje. Po prostu argumenty są tego samego typu i tak to wygląda. No ok - poza dwoma case'ami. W tych dwóch caseach używam tej samej funkcji, ale wciąż jest to inny dll node.oczekp pisze: Ja bym na Twoim miejscu jednak zrobił to tak, że dla każdego case dałbym tego samego dlla, z tym, że dla każdego stanu wywoływał odpowiednią funkcję. No chyba, że są jakieś fajniejsze i mądrzejsze rozwiązania.
PS> Czyli używasz LV 32bitowe z 32 bitowymi dllkami?:)
Nie jestem pewny co rozumiesz przez używanie LV 32 bitowego. Zmienia się gdzieś typ node'a, czy chodzi Ci o mój system ? : > DLL są 32b.
Okazało się, że nie potrzebuję dostępu do obiektów, więc po prostu napisałem swoje funkcje. Być może o czymś zapomniałem ? Nie jest mi też potrzebne definiowanie _cplusplus, bo kompilator VS i tak kompiluje cpp.
Kod: Zaznacz cały
#define DLLIMPORT __declspec (dllexport)
[moje include ""]
#include <sstream>
#include <stdexcept>
#include <memory>
using namespace std;
using namespace adocol;
ODev* device2;
CDev* cdev;
ODev* device1;
extern "C" {
DLLIMPORT void ReadDMC(const char* fileName)
{
\\początek [...] - oznacza, że wyciąłem kod ze względów estetycznych
auto_ptr<Data> newdata;
try {
newdata = auto_ptr<Data>(new Data(string(fileName))); }
catch [...]
try{
device1 = newdata->createOutput(); }
[...]
}
DLLIMPORT void setVoltages(const double* vlt) {
device1->set(vlt);
}
DLLIMPORT void setZernike(const double* zer) {
device2->set(zer);
cdev->sweep();
}
BOOL WINAPI DllMain(
HINSTANCE hinstDLL, // handle to DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpReserved ) // reserved
{
// Perform actions based on the reason for calling.
switch( fdwReason )
{
case DLL_PROCESS_ATTACH:
// Initialize once for each new process.
// Return FALSE to fail DLL load.
break;
case DLL_THREAD_ATTACH:
// Do thread-specific initialization.
break;
case DLL_THREAD_DETACH:
// Do thread-specific cleanup.
break;
case DLL_PROCESS_DETACH:
{
delete device1;
delete device2;
delete cdev;
device1 = NULL;
device2 = NULL;
cdev = NULL;
}
break;
}
return TRUE; // Successful DLL_PROCESS_ATTACH.
}
}
Ostatnio zmieniony 17 sie 2011 23:58 przez Dziech, łącznie zmieniany 1 raz.
DLL C++
Wydaje mi się, że to coś z ścieżkami... Jak usunąłem określanie ścieżki do DLL z Block Diagram, LV zaczął przeglądać dysk twardy w poszukiwaniu DLL. Dałem przeglądaj i wskazałem DLL. W konfiguracji node'a widniała dalej nazwa DLL. Po odpaleniu nie daje błędu. To o node z stringiem.
Natomiast node'y w caseach po zrobieniu tego samego, dają błąd :
Error 1097 occurred at Call Library Function Node in mirrorcontrol.vi
LabVIEW: An exception occurred within the external code called by a Call Library Function Node. The exception might have corrupted the LabVIEW memory. Save any work to a new location and restart LabVIEW.
Natomiast node'y w caseach po zrobieniu tego samego, dają błąd :
Error 1097 occurred at Call Library Function Node in mirrorcontrol.vi
LabVIEW: An exception occurred within the external code called by a Call Library Function Node. The exception might have corrupted the LabVIEW memory. Save any work to a new location and restart LabVIEW.
Ostatnio zmieniony 18 sie 2011 20:14 przez Dziech, łącznie zmieniany 2 razy.
DLL C++
Wstawiłem
jako warunek wykonania każdej funkcji (orpócz oczywiście readDMC) i DLL działa. Pomijając fakt, że działa tylko jak określę ścieżkę w konfiguracji a nie przez nazwę i kontrolkę Current VI's path...
Czyli problem jest w tworzeniu obiektów ODev i CDev (wygląda na to, że są NULL nawet po utworzeniu). Co to może być ? : /
Kod: Zaznacz cały
if(deviceX)
Czyli problem jest w tworzeniu obiektów ODev i CDev (wygląda na to, że są NULL nawet po utworzeniu). Co to może być ? : /
Ostatnio zmieniony 19 sie 2011 11:38 przez Dziech, łącznie zmieniany 1 raz.
Re: DLL C++
A spróbuj podając nie samą ścieżkę tylko ścieżkę z nazwą pliku dll, tak jak w załączniku.Pomijając fakt, że działa tylko jak określę ścieżkę w konfiguracji a nie przez nazwę i kontrolkę Current VI's path...
Zauważ, że current vi path daje nazwę ścieżki, w której jest vi plus na końcu nazwę vi, które tą funkcję wywołuje.
Co do obiektów ODev i Cdev to zerknę wieczorkiem, bo teraz nie bardzo mam na to czas.
A jak ręcznie podajesz podczas konfiguracji ścieżkę do dll i uruchomisz bez if(deviceX) to też się krzaczy?
- Załączniki
-
- snip.png (15.79 KiB) Przejrzano 12433 razy
Re: DLL C++
Tak, też wylatuje błąd. Zaraz spróbuję porobić coś z tym co podałeś. Próbowałem debuggować z VS, ale daje błąd, nie pamiętam dokładnie, ale coś z uszkodzeniem stosu.
Zrobiłem jak napisałeś - wywala błąd
LabVIEW: An exception occurred within the external code called by a Call Library Function Node. The exception might have corrupted the LabVIEW memory. Save any work to a new location and restart LabVIEW.
Ale tylko w DLL node z case. Przy odczycie pliku nie czepia się...
Zrobiłem jak napisałeś - wywala błąd
LabVIEW: An exception occurred within the external code called by a Call Library Function Node. The exception might have corrupted the LabVIEW memory. Save any work to a new location and restart LabVIEW.
Ale tylko w DLL node z case. Przy odczycie pliku nie czepia się...