Tomasz B.

Tomasz B. Senior Software
Engineer

Temat: Kompilacja Native DLL do .NET

Witam

Chce użyć taki projekt MRPT napisany w C++ kompiluje go w Microsoft Visual Studio C++ 2010 Express zgodnie z instrukcja http://www.mrpt.org/Building_and_Installing_Instructions . Uzyskuje bibliotekę nativ DLL i tu się pojawia problem.
Mój robot jest napisany w C# i chce użyć tych bibliotek z MRPT ale nie mogę ich dodać do swojego projektu. Dostaje komunikat „A reference to libmrpt-base095-dbg.dll could not be added. Please make sure that the file is accessible, and that as a valid assembly or COM component”.

Moje pytanie jest takie czy istnieje możliwość ustawić coś Microsoft Visual Studio C++ 2010 tak by mi projekt przekompilował projekt jako bibliotekę dll .NET tak bym mógł ją prosto dodać do swojego C#.
Nie znam się na C++ i nie wiem czy to kwestia kodu czy nieprawidłowej kompilacji. Na forum MRPT nie doczekałem się odpowiedzi. Może w Property tak jak na screen.

Obrazek
Jan Kowalski

Jan Kowalski Specjalista

Temat: Kompilacja Native DLL do .NET

Masz kilka sposobow na udostepnienie natywnego kodu do zarzadzanego C#.
Z tego co napisales, to najprostrze moim zdanie by bylo po prostu stworzenie zarzadzanych wrapperow dla natywnych funkcji.

zrob:



ref class Wrapper
{
// i tutaj wrappery
}


Potem w .NETowej aplikacji dodaj referencje do tak skompilowanej biblioteki.
Nie zapomnij o /clr w natywnej bibliotece.

konto usunięte

Temat: Kompilacja Native DLL do .NET

Lub użyć DllImport http://www.dotnetperls.com/dllimport
Ja osobiście robię tak, że ładuję dll jako resources, przy uruchamianiu aplikacji Net rozpakowuje do tempa następnie poprzez LoadLibrary linkuję i wołam w ten sposób wyeksportowane metody z natywki. Pamiętaj o GC i referencjach ( delegatach ) aby pamiętać ich adresy pod int.

Pozdr.
Sławomir Orłowski

Sławomir Orłowski PhD, physicist,
software
developer/architect
team leader...

Temat: Kompilacja Native DLL do .NET

Cześć,
Masz dwie opcje do wyboru:
1. Użycie C# i DllImport
2. Użycie C++/CLI i napisanie wrappera

Wybór zależy przede wszystkim od rozmiarów API biblioteki natywnej oraz sposobów jej użycia. W ogólności znacznie łatwiej jest użyć C++/CLI. Jest bardziej elastyczne i masz większą kontrolę w porównaniu do C# i DllImport.

W natywnej bibliotece nie musisz używać przełącznika /clr. Nawet lepiej go nie używaj. Natywną bibliotekę skompiluj jako natywną (bez /clr) i napisz wrapper w C++/CLI.
Jest kilka spraw na które dobrze jest uważać:
Wskaźniki na kod zarządzany (np. delegaty wyeksportowane jako wskaźniki do funkcji).

Zakres zmiennych. Najlepiej wszystko co "wchodzi" z kodu zarządzanego do niezarządzanego trzymać jako pola klasy wrappera. Unikniesz wtedy zebrania takich elementów przez GC.

Trzeba uważać, żeby GC nie "zjadło" Ci obiektu w momencie jego użycia w kontekście niezarządzanym (to w zasadzie kontynuacja wskazówki powyżej)

Trzeba pamiętać, że przy zmianie kontekstów wykonania zarządzany/niezarządzany masz pewne narzuty. Na pewno ogranicza to wydajność. Ogranicz więc liczbę takich transakcji.

Nie bój się GC.Collect()

To tak na początek. Będziesz miał problemy - daj znać.
Tomasz B.

Tomasz B. Senior Software
Engineer

Temat: Kompilacja Native DLL do .NET

Sorki że odpisuję dopiero teraz ale urlop i nie miałem kompa, dziękuję za pomoc napisałem wstępnie Wrapera, zapowiada się że będzie działać, jak wszystko sprawdzę dam znać. Dzięki pozdrawiam
Krzysztof Mierzejewski

Krzysztof Mierzejewski SharePoint
Consultant

Temat: Kompilacja Native DLL do .NET

Opcja nr 3. COM.
Sławomir Orłowski

Sławomir Orłowski PhD, physicist,
software
developer/architect
team leader...

Temat: Kompilacja Native DLL do .NET

Krzysztof Mierzejewski:
Opcja nr 3. COM.
A próbowałeś? Bo moim zdaniem to jest ostatnia z opcji do rozważenia, jeśli inne z jakiegoś powodu zawiodą.
Krzysztof Mierzejewski

Krzysztof Mierzejewski SharePoint
Consultant

Temat: Kompilacja Native DLL do .NET

Sławomir Orłowski:
A próbowałeś? Bo moim zdaniem to jest ostatnia z opcji do rozważenia, jeśli inne z jakiegoś powodu zawiodą.

Ja bym posortował listę naszych 3 opcji w następujący sposób:
1. C++/CLI
2. COM
3. DllImport

Dlaczego COM przed DllImport (i w sumie z tego sameg powodu C++/CLI na pierwszym miejscu)? Po prostu większe wsparcie ze strony frameworka - mamy PIA i TlbImp, pozwala nam to na użycie "obiektowości" COM w przeciwieństwie do P/Invoke, gdzie tak naprawdę mamy po prostu zbiór procedur. W .NET 4.0 doszedł też dynamic i named / optional parameters, wygodna sprawa przy interopie. Kolejna temat to taki, że w C# można łatwo stworzyć CCW i mieć dzięki temu serwer COMowy, ale już DllExport brakuje (to znaczy w C#, w .NET w ogóle da się wystawić na zewnątrz entry point z C-like naming convention).

Wracając do pytania - próbowałem. Nie było większych problemów. Trzeba tylko pamiętać o trzech rzeczach:
1. RCW jest per AppDomain i zwiększa COM reference counter przy marshalingu z jednej do drugiej (z tego co wiem to jedyny sposób na zwiększenie COM reference counter poza explicite stworzeniem kolejnego RCW przez Marshal.GetUniqueObjectForIUnknown() czy Marshal.AddRef()). Dobrze zadbać, żeby na końcu został zmniejszony do 0, czy to przez unload AppDomains czy to przez FinalReleaseComObject we wszystkich AppDomains (albo marshal.Release(IntPtr), ale takie zarządzanie counterem zaczyna być tricky). Trochę informacji tutaj.
2. RCW potrafi być tworzony on demand i dobrze przytrzymać do niego referencję, jeżeli mamy zamiar używać jakiegoś jego interface. Więcej tutaj.
3. Najzabawniejsze - RCW sam z siebie nie dekrementuje internal reference counter (nie mylić z COM reference counter, ten jest zazwyczaj 1 per RCW) przy passing scope boundary. Trzeba samemu z siebie zrobić Marshal.ReleaseComObject(object) jeżeli nie mamy zamiaru przetrzymywać referencji do na przykład przekazanego interfejsu. Więcej tutaj.

Bottomline: COM nie trzeba się bać. Trzeba mu poświecić trochę czasu, ale zawsze można zrobić własny serwer COMowy w .NET i trochę podebugować :)Krzysztof Mierzejewski edytował(a) ten post dnia 30.01.12 o godzinie 18:17
Tomasz B.

Tomasz B. Senior Software
Engineer

Temat: Kompilacja Native DLL do .NET

A czy jak żeby z COM opcji skorzystać to biblioteka nie musi być zarejstrowana w resjestrze systemowym poprzez regsvr32 ? Coś takiego pamiętam ale może się mylę w każdym razie ja swoje bibiloteki nativ próbowałem rejestrować niestety bezskutecznie zły typ biblioteki
Sławomir Orłowski

Sławomir Orłowski PhD, physicist,
software
developer/architect
team leader...

Temat: Kompilacja Native DLL do .NET

Tomasz B.:
A czy jak żeby z COM opcji skorzystać to biblioteka nie musi być zarejstrowana w resjestrze systemowym poprzez regsvr32 ? Coś takiego pamiętam ale może się mylę w każdym razie ja swoje bibiloteki nativ próbowałem rejestrować niestety bezskutecznie zły typ biblioteki
Słuchaj w Twoim przypadku najlepiej napisać opakowanie w C++/CLI. COM jest wyciąganiem armaty do ustrzelenia muchy. Nie chodzi przy tym o moje obawy w stosunku do COM, jak to napisał Krzysztof. Moim zdaniem nie ma jednego dobrego powodu, dla którego miałbyś wyciągać całą maszynerię COM w Twoim projekcie. Stopień komplikacji jest znacznie mniejszy przy zastosowaniu C++/CLI. Jeśli natywne API jest niezbyt duże (kilka funkcji) to jeszcze lepiej użyć Platform Invoke i DllExport. Korzystałem dużo z technologii łączenia kodów (zarządzany+niezarządzany).

Używałem na początku DllImport, ale natywne API było skomplikowane. Nie sprawdziło się importowanie funkcji, "wypłaszczenie", opakowanie w obiekt zarządzany. Dużo komplikacji.

Używałem COM. Ze względów wydajnościowych i stopnia komplikacji zrezygnowałem. Oczywiście nie chodzi tu o samą technologię, która jest ciekawa, tylko o aplikacje jakie ja tworzę. COM się nie nadaje.

Zacząłem używać C++/CLI i okazał się być najlepszy. Mam pełną kontrolę nad całością wykonywania kodu. Jest zdecydowanie prościej i wydajniej niż w COM.

Z mojego doświadczenia istnieją dwa godne uwagi podejścia:
C++/CLI
Platofrm Invoke z DllImport

BTW. Dynamic i named/optional parameters są dobre do wciągania obiektów interop z MS Office. Nie próbowałem ich użycia w moich projektach. Muszę je sobie przetestować.
Krzysztof Mierzejewski

Krzysztof Mierzejewski SharePoint
Consultant

Temat: Kompilacja Native DLL do .NET

Tomasz B.:
A czy jak żeby z COM opcji skorzystać to biblioteka nie musi być zarejstrowana w resjestrze systemowym poprzez regsvr32 ? Coś takiego pamiętam ale może się mylę w każdym razie ja swoje bibiloteki nativ próbowałem rejestrować niestety bezskutecznie zły typ biblioteki

Powiem tak, teoretycznie się da, chociaż ja w ten sposób nigdy nie próbowałem. Natomiast jeżeli nie jesteś w stanie zarejestrować z użyciem regsvr to registration context też powinien nie działać (z tego samego powodu). Jesteś pewien, że masz poprawną implementację IUnknown?
Tomasz B.

Tomasz B. Senior Software
Engineer

Temat: Kompilacja Native DLL do .NET

Jan Kowalski:
Masz kilka sposobow na udostepnienie natywnego kodu do zarzadzanego C#.
Z tego co napisales, to najprostrze moim zdanie by bylo po prostu stworzenie zarzadzanych wrapperow dla natywnych funkcji.

zrob:



ref class Wrapper
{
// i tutaj wrappery
}


Potem w .NETowej aplikacji dodaj referencje do tak skompilowanej biblioteki.
Nie zapomnij o /clr w natywnej bibliotece.

Właśnie metodę powyższą wybrałem do wykorzystania biblioteki, o tyle dobrze że posiadam źródła do tych bibliotek więc nie było problemu napisać wrappera.
Jedyne co mi się nie podoba to muszę większość napisać w C++, a tego języka ostatnio używałem na studiach.
W każdym razie dziękuje wszystkim za pomoc. pozdrawiam.

Następna dyskusja:

Kompilacja do systemów x64




Wyślij zaproszenie do