2012-12-27 7 views
6

Sto usando una DLL nativa. Non sono sicuro, ma penso di non poter usare PInvoke decl con esso poiché non esporta nessuna funzione e non ha manifest. La DLL viene consegnata con un file di intestazione, che spiega come usarlo. Il file di intestazione definisce infinite strutture, enumerazioni e una classe da costruire utilizzando un metodo factory a cui si accede tramite una funzione di Windows ::GetProcAddress (security through obscurity). Questa classe contiene funzioni che vorrei utilizzare nel codice gestito.E 'possibile effettuare il marshalling dell'array struct nativo sull'array gestito senza un ciclo for

Ho completato con successo la classe in una classe di riferimento CLI e posso richiamare metodi banali, avvolgendo anche quelli.

Sto passando attraverso il processo di conversione di alcune strutture dal file di intestazione alle strutture gestite. Ad esempio, i nativi struct:

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

si trasforma in struct gestito:

[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; 
}; 

Per quanto posso dire questo dovrebbe rendere il copiabili struct gestito? E qualsiasi altra struttura che segue uno schema o livelli simili di struttura annidata. Finché viene specificato un layout e nessuno può essere abbinato a MarshalAs, la struttura nel suo complesso può essere scelta?

E così, sto cercando di vedere se c'è un modo per utilizzare Marshal::Copy o Marshal::PtrToStructure per convertire una matrice FooACL*-array<ManagedFooACL>^.

Ricevo l'array FooACL * da una chiamata di funzione; Non lo assegno da solo.

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

total è un fuori in/che ottiene la dimensione dell'array restituito.

cosa sono riuscito a fare finora, e ciò che il lavoro è:

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

Quello che non posso avvolgere la mia mente intorno perché questo non lo fa:

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

Questo getta una:

C'è un modo per copiare i dati dell'array in una chiamata o devo davvero fare un ciclo for? Sembra un po 'sciocco con tutte queste capacità di marshalling.

+0

Nota: se è possibile accedere alla funzione utilizzando 'GetProcAddress', la funzione viene esportata e può essere richiamata tramite pinvoke. –

+0

Sono d'accordo, ma questa è solo una funzione di fabbrica che mi dà una classe che detiene la maggior parte delle funzionalità che sto cercando. – Dmitry

+0

Giusto, non volevo dire che è pratico farlo, solo notandolo per riferimenti futuri. :) –

risposta

2

Dopo aver fatto qualche ricerca in più, la risposta è no. Non è possibile effettuare il marshalling automatico di s senza looping.

Penso che il motivo principale per il marshalling struct sia PtrToStructure perché la struttura è statica/predefinita. Il compilatore sa come disporre la memoria. Dal momento che si ottiene una dimensione dinamica array non è possibile specificare la disposizione della memoria in anticipo. Quindi è necessario eseguire il ciclo del numero dinamico di struct s.

In alternativa, se si sapeva che vi sarà sempre trovato un array di lunghezza X, è possibile definire il proprio gestito struct tenendo un elemento, cioè la matrice di ManagedFooACL con un valore ByValArray e SizeConst di X, e solo il cast del nativo array allo struct.

Problemi correlati