2010-03-28 19 views
23

Czy warto łączyć C++ i C#, czy może to powodować problemy?Łączenie C++ i C#

Mam aplikacji, która musi być jakieś części do C++, a niektóre części będzie C# (dla zwiększenia wydajności). Jaki byłby najlepszy sposób do osiągnięcia przy użyciu natywnej biblioteki dll C++ w C#?

Odpowiedz

25

Tak przy użyciu C# i C++ dla danego produktu jest bardzo powszechne i jest dobrym pomysłem.

Czasami można użyć Managed C++, w którym to przypadku można użyć zarządzanej C++ moduł tak jak każdy inny moduł .NET.

Zwykle robisz wszystko, co możliwe w języku C#. W przypadku części, które musisz wykonać w C++, zwykle tworzysz DLL w C++, a następnie wywołujesz tę bibliotekę DLL z C#. Eliminacja parametrów odbywa się automatycznie dla ciebie.

Oto przykład importowania funkcję C wewnątrz DLL w C#:

[DllImport("user32", CharSet=CharSet.Auto, SetLastError=true)] 
internal static extern int GetWindowText(IntPtr hWnd, [Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpString, int nMaxCount); 
+0

Czy to reklama dla .NET? A co z kompatybilnością między platformami, problemami z połączeniem, krzywą uczenia się itp.? –

+1

Krzywa uczenia? Przypuszczam, że znasz podstawy zarówno C++, jak i C#, gdy próbujesz łączyć języki. Cross platform? To oczywiste, że pisanie kodu w języku C++ jest o wiele trudniejsze, ale możliwe. Wydaje się jeszcze łatwiejsze w połączeniu z C# - kod wyższego poziomu może decydować, które części C/C++ załadować i użyć na konkretnej platformie. – Harry

+0

@Harry: Przyjmuję twoją odpowiedź, kiedy pokazujesz mi (np.) C# działającego na PIC ;-) –

29

Pytanie jest jasno jak zintegrować swój własny kod C++ do jego C# rozwiązania, a nie tylko to, co przypisują do wykorzystania w celu aby wywołać istniejącą funkcję z API win32. Nawet jeśli odpowiedź została już zaakceptowana, myślę, że jest ona niekompletna i powinny obowiązywać następujące zasady.

Tak, to jest powszechną praktyką w przypadku, gdy zadanie może uruchamiać się szybciej, zużywają mniej zasobów, a także w niektórych przypadkach do metod dostępu, które nie są dostępne w .NET Framework.

Jeśli twoim celem jest uzyskanie wydajności trzeba kodować natywną niezarządzanego C++ biblioteki, można utworzyć nowy projekt niekontrolowana C++ (który kompiluje jako biblioteka DLL) w Visual Studio i odniesienia tej biblioteki z projektu C# .

W twoim przypadku wydaje się możesz pisać niezarządzanego biblioteka C++, i stosuje następujące.

Jeśli chodzi o wszelkie bieżące problemy, o które pytałeś o numer, miałoby to wpływ na rozmieszczenie i zaciemnianie.

  • Wdrożenie: Należy pamiętać, że C# DLL budować będzie działać na każdym procesora, zarówno 32 i 64-bitowe, ale ta nowa rodzimych i niekontrolowana C++ biblioteka będzie zmusić program aby być dla 32 lub 64 konkretne.

    To jest coś będzie skonfigurowanie w Visual menedżera konfiguracji Studio i zostaną załatwione w czasie kompilacji czasu, można wybrać AnyCPU dla C# zespołów i dla nowego niezarządzanego C++ biblioteki, która będzie w to jest własny projekt, będziesz mieć do wyboru z win32 lub x64.

    Więc teraz masz 2 konfiguracje, to poleca najlepsze praktyki mieć różne konfiguracje, jeden dla 32 i drugi dla 64. A ponieważ 32bit poparcie spada bardzo szybko, można skupić się na 64bit tylko.

    Twoja biblioteka może również odnosić się do redystibutu VC++ udostępnianego przez Visual Studio, który być może będziesz musiał dołączyć do swojego wdrożenia, chociaż pewna jego wersja jest zawarta w wielu systemach operacyjnych. Zauważyłem, że rzadko jest to ta sama, którą skompilowałem z i najlepiej jest wdrożyć go z aplikacją, aby mieć pewność. Jeśli tego pakietu nie ma, komputer docelowy będzie miał wyjątek SideBySide w dzienniku zdarzeń-> aplikacja.

    Aby uchwycić i obsłużyć wyjątek wyrzucony z kodu niezarządzanego, jedynym haczykiem, który działa, jest ten, który działa bez nawiasu w nawiasie po znaku catch(). Więc możesz zawijać swoje wywołania do kodu niezarządzanego w tym celu, aby obsłużyć wszystkie niezarządzane wyjątki wyrzucone z niezarządzanego kodu, jeśli umieścisz typ .net typu catch (Exception), to przeskoczy go. Jedynym sposobem na złapanie niezarządzanego wyjątku wewnątrz kodu zarządzanego jest ten format.


    try 
    { 
     //call unmanaged code 
    } 
    catch 
    { 
     //handle unmanaged exception 
    } 

  • zaciemniania: Wszelkie wywołania metod zrobić z C#, które są teraz wywołanie kod niezarządzanej zostanie wykluczony od zmiany nazwy automatycznie. I na odwrotną stronę, jeśli niekontrolowana biblioteki C++ potrzebuje zadzwonić metody z zarządzanych zespołów, te będą musiały być wyłączone z zmiana nazwy, ręcznie, aby być widoczne dla C++ biblioteki wywołującego im.

Jeśli potrzebujesz tylko wywołać dobrze znane biblioteki C++, takie jak Windows, NIE będziesz musiał tworzyć nowego niezarządzanego projektu C++, używaj tylko atrybutu [DllImport()] sugerowanego w poprzedniej odpowiedzi. I w tym przypadku można przyjrzeć się tej publikacji http://www.pinvoke.net/

+0

* "złap i obsłuż wyjątek wyrzucony z niezarządzanego kodu" * - Myślę, że należy to zmienić, specyfikacja typu catch bez wyjątku oznacza tylko wychwytywanie wyjątków. Nie ma łatwego sposobu na specyficzną obsługę, ale przechwytywanie utrzymuje działanie aplikacji C# ... Zobacz także [.net - czy możesz złapać natywny wyjątek w kodzie C#? - Stack Overflow] (https://stackoverflow.com/questions/150544/can-you-catch-a-native-exception-in-c-sharpcode) i [CA2102: Catch niezgodne z CLSC wyjątki w ogólnych procedurach obsługi] (https://msdn.microsoft.com/en-gb/bb264489.aspx) – Wolf

-2

dodatkowe informacje na temat różnic w porównaniu do C# C++ i possibles kwestii ich scalania:

  • C# jest interpretowany, jak Java. C++ jest skompilowany do natywnego pliku binarnego. Zawierają one kilka różnic wyjaśnionych dalej w następujących punktach.
  • Zgodność z platformą: C#, zgodnie z interpretacją i produktem Microsoft, działa dobrze na Windowsie, poprawnie na Linuksie dzięki świetnemu projektowi Mono, ale nie na tyle dobrze (lub w ogóle) na innych platformach (Android, IOS, inne .) Jeśli chcesz napisać oprogramowanie do osadzenia tam, gdzie nie ma wsparcia dla systemu operacyjnego lub napisać samego systemu operacyjnego, w większości przypadków "nie możesz" używać C#. C++ jest całkowicie wieloplatformowy, jak tylko masz kompilator (co zwykle ma miejsce).
  • Kod interpretowany jest zwykle o jeden rząd wielkości wolniejszy niż kod binarny [1]. To dlatego użyjesz C++ połączonego.
  • Kod binarny a kod pośredni: Kod pośredni działa na dowolnym tłumaczu dostępnym w konkretnej architekturze, C++ wymaga przekompilowania dla każdej architektury.
  • Krzywa uczenia: Programista musi nauczyć się kilku języków, co wydłuża czas nauki. Trudniej jest też znaleźć ekspertów w obu językach.
  • IDE: Dla C++ wystarczy dowolny edytor tekstu, ponieważ C# będzie wymagać określonego IDE.
  • Real-time: Trudno wyobrazić sobie warunki w czasie rzeczywistym za pomocą C#.
  • Niektóre certyfikaty jakości mogą być niemożliwe do uzyskania przy pomocy kodu C# (oprogramowanie krytyczne).

Czy to dobry pomysł, aby je połączyć?

To prawdopodobnie zależy od twojego projektu. W przypadku dużych projektów HMI w systemie Windows może to poprawić czas programowania. Jednak inne wymagania dotyczące oprogramowania mogą ograniczyć tylko do C++.


[1] Czytałem wiele razy, że interpretowane kod jest w niektórych przypadkach nawet szybciej niż kod binarny, to ze względu na błędne: Interpreter realizuje kilka funkcji dla wygody, więc podczas rozmowy (np) sort(), w rzeczywistości wywołuje binarną implementację tej funkcji. Jeśli ta funkcja jest dobrze zoptymalizowana, ostateczny czas może być szybszy, ale tylko dlatego, że wszystkie działają w systemie binarnym, a interpretowany komponent jest minimalny w porównaniu do całego czasu wymaganego do sortowania. Z drugiej strony, jeśli zakodujesz pełną logikę w obu językach, wersja binarna zawsze będzie znacznie szybsza. Powód jest prosty: interpreter jest binarnym, który oprócz twojego kodu uruchamia cały framework językowy.

+1

Jit to nie to samo co zinterpretowane. Jit może się kompilować do kodu maszynowego. – tohava

+0

Nawet przy "w pełni skompilowanym" C#, co nie jest typowe, większość afirmacji tutaj jest nadal aktualna. Tylko, że nie jest to interpretowane, a różnica między wynikami nie jest aż tak duża. –