| Both sides previous revisionPrevious revisionNext revision | Previous revision |
| pl:edu:zmitac:n1z:ja:lab3 [2021/04/11 17:38] – [Przekazywanie wskaźników z poziomu C# do funkcji w assemblerze] pczekalski | pl:edu:zmitac:n1z:ja:lab3 [2022/04/23 16:03] (current) – [Konfiguracja środowiska] pczekalski |
|---|
| <note warning>Przed wykonaniem pierwszej kompilacji folder nie zostanie założony, zatem nie będzie można go wybrać za pomoca przycisku [Browse...]. W związku z tym należy wykonać pustą kompilację wyłącznie projektu DLL w celu utworzenia folderu wynikowego.</note> | <note warning>Przed wykonaniem pierwszej kompilacji folder nie zostanie założony, zatem nie będzie można go wybrać za pomoca przycisku [Browse...]. W związku z tym należy wykonać pustą kompilację wyłącznie projektu DLL w celu utworzenia folderu wynikowego.</note> |
| <note warning>Powyższa konfiguracja zapisuje na stałe ścieżkę w konfiguracji projektu. Oznacza to, że zmiana z trybu Debug na Release wymaga zmiany ww. ścieżki!</note> | <note warning>Powyższa konfiguracja zapisuje na stałe ścieżkę w konfiguracji projektu. Oznacza to, że zmiana z trybu Debug na Release wymaga zmiany ww. ścieżki!</note> |
| | |
| | W przypadku, gdyby pomimo ustawienia wspólnego folderu wynikowego nadal były zgłaszane błędy braku biblioteki DLL, istnieje możliwość, że włączony jest system tworzenia dodatkowych podfolderów, jak to opisano poniżej w notce z uwagami. Aby usunąć ten problem, konieczne jest ręczna edycja pliku konfiguracyjnego projektu.\\ Aby otworzyć plik konfiguracyjny projektu, należy dwukrotnie klinąć nazwe projektu w drzewie. Otworzy się plik typu XML, z rozszerzeniem ''.csproj''. |
| | |
| | <note warning>Uwaga! W przypadku projektu WPF w folderze wynikowym może pojawić się podfolder z wersją frameworku .NET, co w praktyce spowoduje, że plik wykonywalny z frontside (GUI) zostanie uruchomiony w innym folderze (w podfolderze) w stosunku do wybranego w ustawieniach, skutkiem czego biblioteka DLL nie zostanie załadowana i zostanie zgłoszony wyjątek. Podfoldery te są dodawane automatycznie. Aby usunąć tę niedogodność, w pliku projektu WPF należy mieścić dodatkową sekcję((https://docs.microsoft.com/en-us/visualstudio/ide/how-to-change-the-build-output-directory?view=vs-2019)): |
| | <code xml> |
| | |
| | <PropertyGroup> |
| | <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath> |
| | <AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath> |
| | </PropertyGroup> |
| | |
| | </code> |
| | </note> |
| |
| === Konfiguracja na potrzeby kodu unsafe oraz debuggowania === | === Konfiguracja na potrzeby kodu unsafe oraz debuggowania === |
| Do ustawienia pozostają jeszcze dwie opcje: | Do ustawienia pozostają jeszcze dwie opcje: |
| * Włączenie użycia kodu "unsafe", o ile dyrektywa "unsafe" jest wymagana. Dyrektywy tej nie trzeba używać m.in. w przypadku wykorzystywania struktury ''IntPtr'' do przekazywania wskaźników oraz w przypadku przekazywania argumentów przez wartość, niemniej jednak zalecane jest jej włączenie. W tym celu we właściwościach projektu w języku C# należy w sekcji "Build" w grupie"General" zaznaczyć opcję "Allow unsafe code" (rysunek {{ref>asm3_13}}); | * Włączenie użycia kodu "unsafe", o ile dyrektywa "unsafe" jest wymagana. Dyrektywy tej nie trzeba używać m.in. w przypadku wykorzystywania struktury ''IntPtr'' do przekazywania wskaźników oraz w przypadku przekazywania argumentów przez wartość, niemniej jednak zalecane jest jej włączenie. W tym celu we właściwościach projektu w języku C# należy w sekcji "Build" w grupie"General" zaznaczyć opcję "Allow unsafe code" (rysunek {{ref>asm3_13}}); |
| * Włączenie debuggowania kodu natywnego, co pozwoli na płynne przełączanie pomiędzy kodem wywołującym w C# i wywoływanym w assemblerze w jednej sesji debuggera. W tym celu we właściwościach projektu w jezyku C# należy wybrać sekcję "Debug", a następnie w grupie opcji "Debugger engines" zaznaczyć opcję "Enable natie code debugging" (rysunek {{ref>asm3_14}}); | * Włączenie debuggowania kodu natywnego, co pozwoli na płynne przełączanie pomiędzy kodem wywołującym w C# i wywoływanym w assemblerze w jednej sesji debuggera. W tym celu we właściwościach projektu w jezyku C# należy wybrać sekcję "Debug", a następnie w grupie opcji "Debugger engines" zaznaczyć opcję "Enable natie code debugging" (rysunki {{ref>asm3_14}},{{ref>asm3_14_2}}); |
| |
| <figure asm3_13> | <figure asm3_13> |
| <figure asm3_14> | <figure asm3_14> |
| {{:pl:edu:zmitac:n1z:ja:virtualbox_msedge_-_win10_06_04_2021_22_48_59.png?600|}} | {{:pl:edu:zmitac:n1z:ja:virtualbox_msedge_-_win10_06_04_2021_22_48_59.png?600|}} |
| <caption>Włączenie debuggowania kodu niezarządzalnego</caption> | <caption>Włączenie debuggowania kodu niezarządzalnego (VS do wersji 2019 włącznie, .NET do wersji 5)</caption> |
| | </figure> |
| | <figure asm3_14_2> |
| | {{:pl:edu:zmitac:n1z:ja:virtualbox_msedge_-_win10_-_ja_nsi_23_04_2022_16_00_45.png?600|}} |
| | <caption>Włączenie debuggowania kodu niezarządzalnego (VS od wersji 2022 włącznie, .NET 6.0)</caption> |
| </figure> | </figure> |
| |
| W powyższym przykładzie pominięto przekazywanie do funkcji długości tablicy, gdyż jej rozmiar (6 elementów) jest z góry znany. W przypadku, gdy rozmiar tablicy jest zmienny, należy przekazać do funkcji w assemblerze jej długość jako osobny parametr. | W powyższym przykładzie pominięto przekazywanie do funkcji długości tablicy, gdyż jej rozmiar (6 elementów) jest z góry znany. W przypadku, gdy rozmiar tablicy jest zmienny, należy przekazać do funkcji w assemblerze jej długość jako osobny parametr. |
| |
| <note important>Uwaga! Tablice po stronie kodu w C# są alokowane liniowo. Ponieważ jednak w C# nie da się w prosty sposób otrzymać wskaźnika do obiektu, który nie jest typem prostym (a tablica nim nie jest), używamy pewnego obejścia polegającego na tym, że pobieramy adres do pierwszego elementu tablicy, zamiast do całego obiektu tablicy (ostatecznie, w przypadku tablicy typów prostych, adresy będą takie same). Adres kolejnego elementu w tablicy to po prostu adres pierwszego + rozmiar zmiennej, itd. Elementy tablicy są alokowane bez wyrównania do 64 bitów. Dopiero po ostatnim elemencie może pojawić się wyrównanie (o ile będzie konieczne).</note> | <note important>Uwaga! Tablice po stronie kodu w C# są alokowane liniowo. Ponieważ jednak w C# nie da się w prosty sposób otrzymać wskaźnika do obiektu, który nie jest typem prostym (a tablica nim nie jest), używamy pewnego obejścia polegającego na tym, że pobieramy adres do pierwszego elementu tablicy, zamiast do całego obiektu tablicy. Ostatecznie, w przypadku tablicy typów prostych, adresy będą takie same. Elementy pojedynczej tablicy są alokowane bez wyrównania do 64 bitów. Dopiero po ostatnim elemencie może pojawić się wyrównanie (o ile będzie konieczne). Wyrównanie widać w kolejnym przykładzie, gdzie korzystamy ze struktury.</note> |
| |
| Przykładowy kod w assemblerze, który zwraca wskazany element tablcy, może wyglądać następująco: | Przykładowy kod w assemblerze, który zwraca wskazany element tablcy, może wyglądać następująco: |