2012-12-27 13 views
6

Używam natywnej biblioteki DLL. Nie jestem pewien, ale myślę, że nie mogę używać deceleracji PInvoke z nim, ponieważ nie eksportuje żadnych funkcji i nie ma manifestu. Plik DLL jest dostarczany z plikiem nagłówkowym, wyjaśniającym, jak z niego korzystać. Plik nagłówkowy definiuje niezliczone struktury, wyliczenia i jedną klasę do skonstruowania przy użyciu metody fabrycznej dostępnej za pośrednictwem funkcji Windows ::GetProcAddress (bezpieczeństwo przez zaciemnienie). Ta klasa zawiera funkcje, które chciałbym używać w zarządzanym kodzie.Czy można odtworzyć macierz natywną struct tablicy do zarządzanej tablicy bez pętli for?

Udało mi się owinąć klasę w klasę ref CLI i można wywołać trywialne metody, zawijając je również.

Przechodzę proces konwertowania niektórych struktur z pliku nagłówkowego do zarządzanych struktur. Dla przykładu, Native kodowanym:

struct FooACL{ 
    int    action;     
    unsigned long  from,to;    
    char    comment[64]; 
    int    reserved[17];   
}; 

zamienia zarządzanej struktury:

[StructLayout(LayoutKind::Sequential, CharSet = CharSet::Ansi)] 
public value struct ManagedFooACL{ 
    int action;     
    int from,to;  
    [MarshalAs(UnmanagedType::ByValTStr, SizeConst = 64)] 
    String^ comment; 
    [MarshalAs(UnmanagedType::ByValArray, SizeConst = 17)] 
    array<int>^ reserved; 
}; 

O ile mogę powiedzieć, to powinien dokonać zarządzanego struct blittable? I każda inna struktura, która podąża za podobnym wzorcem lub poziomami struktury zagnieżdżonej. Tak długo, jak określona zostanie szata graficzna, a żadna dająca się wyrzeźbić nie zostanie ozdobiona MarshalAs, czy struktura jako całość będzie podatna na blaknięcie?

I tak, ja próbuje sprawdzić, czy istnieje sposób na wykorzystanie Marshal::Copy lub Marshal::PtrToStructure przekonwertować FooACL* tablicę array<ManagedFooACL>^.

Otrzymuję tablicę FooACL * od wywołania funkcji; Nie przydzielam tego samemu.

int total; 
FooACL* foos = unamagedClass->GetFooACLS(&total); 

total jest w /, który pobiera rozmiar tablicy zwrócone.

Co udało mi się zrobić do tej pory, a co praca jest:

ManagedFooACL first = static_cast<ManagedFooACL>(Marshal::PtrToStructure(IntPtr(&foos [0]), ManagedFooACL::typeid)); 

Nie mogę owinąć wokół zdanie to dlaczego nie robi:

array<ManagedFooACL>^ mfoos = gcnew array<ManagedFooACL>(total); 
Marshal::PtrToStructure(IntPtr(&foos), mfoos); 

To rzuca:

System.ArgumentException was unhandled 
    Message=The specified structure must be blittable or have layout information. 
Parameter name: structure 
    Source=mscorlib 
    ParamName=structure 

Czy istnieje sposób na kopiowanie danych tablicy w jednym wywołaniu lub czy naprawdę muszę wykonać pętlę for? Wydaje się to dość głupie przy całej tej zdolności marszałkowej.

+0

Uwaga: Jeśli możesz uzyskać dostęp do funkcji za pomocą 'GetProcAddress', funkcja jest eksportowana i może być wywoływana przez pinvoke. –

+0

Zgadzam się, ale to jest tylko funkcja fabryczna, która daje mi klasę, która ma większość funkcjonalności, której szukam. – Dmitry

+0

W porządku, nie miałem na myśli, że jest to praktyczne, po prostu zwracając uwagę na przyszłe odniesienia. :) –

Odpowiedz

2

Po wykonaniu kilku badań wygląda na to, że odpowiedź brzmi "nie". Nie ma możliwości automatycznego autohalowania array z struct s bez pętli.

Myślę, że głównym powodem struct marshaling działa z PtrToStructure jest, ponieważ struktura jest statyczna/predefiniowane. Kompilator wie, jak rozmieścić pamięć. Ponieważ dostaniesz rozmiar dynamiczny array, nie ma możliwości określenia, z której pamięci chcesz skorzystać. Musisz więc zapętlić numer dynamiczny struct s.

Ewentualnie, jeśli wiedział, że zawsze będziesz coraz tablicę długości X, można zdefiniować własne udało struct trzyma jeden element, a mianowicie tablicę ManagedFooACL z ByValArray i SizeConst wartości X, i po prostu rzucać native array do struct.