Piotr Głudkowski

Piotr Głudkowski Rzucam się na
wszystko to, co jest
ciekawe i wymaga
rusze...

Temat: Pola bitowe z C/C++ a PInvoke

Witam,
robię klasę w C#, będącą wrapperem nad API AutoMapy (API jako dll w C++).

W pliku nagłówkowym z API mam strukturę, wykorzystującą pola bitowe, za pomocą której mam przekazać jeden z argumentów do jednej z wołanych funkcji API.
Po stronie C# muszę więc zrobić klasę, która będzie "odwzorowaniem" tej struktury.
I tu mam problem: wydaje mi się, że robię dobrze, a działa źle.

Zerknijcie na to poniżej, proszę, może rzeczywiście coś spieprzyłem?

Przykładowo, w nagłówku w C++ jest tak:

struct MYSTRUCT
{
DWORD field1 : 8;
DWORD field2 : 24;
int field3;
};


W C# zrobiłem tak:


[StructLayout(LayoutKind.Sequential)]
public class MyClass
{
private UInt32 _combo;
public Int32 Field3;

public UInt32 Field1
{
get { return _combo & 0xff; }
set { _combo = (_combo & 0xffffff00) | (value & 0xff); }
}

public UInt32 Field2
{
get { return (_combo >> 8) & 0x00ffffff; }
set { (_combo & 0xff) | ((value & 0x00ffffff) << 8); }
}
}


No i mam kłopot z wartością Field1 - wygląda na to, że funkcja w API widzi inną wartość, niż to, co wpisuję tam w C#.

Any ideas, please?

Acha, zapomniałem, a to może być istotne: platforma x86.Piotr Głudkowski edytował(a) ten post dnia 02.11.10 o godzinie 13:10
Sylwester Raczyński

Sylwester Raczyński Senior Software
Development
Engineer, Samsung
Electronics...

Temat: Pola bitowe z C/C++ a PInvoke

Może użyj czegoś takiego. Wygląda że lepiej pasuje do twojego przykładu.

[StructLayout(LayoutKind.Explicit)]
public struct Rect
{
[FieldOffset(0)] public int left;
[FieldOffset(4)] public int top;
[FieldOffset(8)] public int right;
[FieldOffset(12)] public int bottom;
}

Cały przykład jest na http://msdn.microsoft.com/en-us/library/system.runtime...

konto usunięte

Temat: Pola bitowe z C/C++ a PInvoke

Sylwester Raczyński:
Może użyj czegoś takiego. Wygląda że lepiej pasuje do twojego przykładu.
W powyższym zdefiniowane są tylko offsety w strukturze a nie ich rozmiary. Jeśli zamiast 0,4,8 i 12 dasz 0,1,2,3 to zapisując coś do left nadpiszesz po kawałku wszystkie pozostałe.

Nie znam na tyle .neta i to dość daleki strzał, ale wpisz w c# jakiś charakterystyczny pattern bitowy (np. 0xAAAAAAFF) i zobacz co dostajesz w c++, może będzie to coś w rodzaju 0xAAFFAAAA (kolejność bajtów/słów).
Maciej Hehl

Maciej Hehl w teorii Automatyk i
Robotyk (po wydziale
mechanicznym), ...

Temat: Pola bitowe z C/C++ a PInvoke

Odpowiedź jest na nos, bo za słabo znam .NET żeby być pewnym, ale mam przeczucie.

Proponuję użyć struktury zamiast klasy.

W C++ to prawie to samo. W .NET różnica jest spora i może być istotna.

Wszystkie przykłady jakie znajdują się w dokumentacji do [StructLayout(LayoutKind.Sequential)] są ze strukturą.

Tu potrzebny jest POD.

Nie znam szczegółów implementacji klas w .NET ale coś mi mówi że z PODem mają niewiele wspólnego. Sam fakt że niejawnie dziedziczą po klasie Object już powoduje, że z klasą związana jest maszyneria do wywoływania funkcji wirtualnych i dodatkowo w .NET mamy refleksję, więc maszyneria związana z jej obsługą też musi być jakoś w klasach zaimplementowana. Ponadto nie jest wykluczone że w .NET enkapsulacja jest na prawdę. Jeśli nawet implementatorzy nie próbują aktywnie walczyć z próbami jej naruszania, co wydaje się być bez sensu, to nie zdziwiłbym się, gdyby specyfikacja pozwalała traktować prywatne pola w specjalny sposób, jeśli chodzi o ich miejsce w klasie. W końcu private znaczy private.

Jeśli struktura musi być na stercie to można ją pewnie zamknąć w klasę lub zrzutować na ObjectMaciej Hehl edytował(a) ten post dnia 02.11.10 o godzinie 20:04
Piotr Głudkowski

Piotr Głudkowski Rzucam się na
wszystko to, co jest
ciekawe i wymaga
rusze...

Temat: Pola bitowe z C/C++ a PInvoke

Zmieniłem już wcześniej. Jest tak samo :(
Ponadto dałem pole _combo jako public. Dalej źle :(
Maciej Hehl

Maciej Hehl w teorii Automatyk i
Robotyk (po wydziale
mechanicznym), ...

Temat: Pola bitowe z C/C++ a PInvoke

Zauważyłem jeszcze, że setter poniżej jest niepoprawny. Nie ma przypisania do pola _combo.

public UInt32 Field2
{
get { return (_combo >> 8) & 0x00ffffff; }
set { (_combo & 0xff) | ((value & 0x00ffffff) << 8); }
}

Więcej pomysłów na razie brak.Maciej Hehl edytował(a) ten post dnia 02.11.10 o godzinie 18:30
Piotr Głudkowski

Piotr Głudkowski Rzucam się na
wszystko to, co jest
ciekawe i wymaga
rusze...

Temat: Pola bitowe z C/C++ a PInvoke

Już się ucieszyłem, że znalazł się błąd :)
Ale okazało się, że w kodzie mam dobrze - przy przepisywaniu do posta zapomniałem o przypisaniu.

Sprawa dalej otwarta :(
Piotr Głudkowski

Piotr Głudkowski Rzucam się na
wszystko to, co jest
ciekawe i wymaga
rusze...

Temat: Pola bitowe z C/C++ a PInvoke

Sprawa się wyjaśniła. To działa dobrze.
Okazało się za to, że API AutoMapy jest na tyle leniwe, że pier...lą mu się wywołania robione zbyt szybko jedno po drugim i stąd efekt widzenia przez API innych wartości, niż były naprawdę.
Wstawienie w jednym miejscu Thread.Sleep(500) rozwiązało sprawę - ciekawe tylko, czy we wszystkich przypadkach :(
Nienawidzę takich rzeczy - chłopakom nie chciało się zrobić jakiegoś blokowania danych i teraz trzeba cudować, żeby to działało. Brrrr...

Temat: Pola bitowe z C/C++ a PInvoke

Od razu przypomina mi się scenka z laboratoriów z asma - obsługa portu szeregowego: "tu proszę wstawić kilka NOPów albo jakąś pętlę, bo UART to lubi". Przy ArcNecie też tak trzeba było, ech, dawne dobre czasy ...... :)

Piotrze, a nie ma jakiegoś potwierdzenia, że API już łyknęło poprzednią wartość? Albo może zamiast czekać 500ms, to wywołać jakąś "nie-robiącą-nic-ważnego" procedurkę tegoż API?Adrian Olszewski edytował(a) ten post dnia 02.11.10 o godzinie 22:25
Piotr Głudkowski

Piotr Głudkowski Rzucam się na
wszystko to, co jest
ciekawe i wymaga
rusze...

Temat: Pola bitowe z C/C++ a PInvoke

Jest niby funkcja, która powinna zwracać status AutoMapy - ale nie działa dobrze, tzn. trzeba chwilę odczekać po jakiejś operacji, zanim się to sprawdzanie wywoła, bo inaczej zwraca, że AM nie jest zajęta :(
Generalnie spierdzielili jak ta lala.

Te 500ms to jest do przełknięcia przez usera - praktyka pokazuje, że jeśli program chodzi _zbyt_ szybko, przestaje być doceniany przez usera :) A tak, user poczeka te 0.5s i... uuuu, ale bajer, AutoMapa się odpaliła i wyznaczyła mi trasę, gdzie mam jechać :)

Następna dyskusja:

Pola bitowe w strukturach -...




Wyślij zaproszenie do