2012-12-27 8 views
6

J'utilise une DLL native. Je ne suis pas sûr, mais je pense que je ne peux pas utiliser PInvoke avec ça, car il n'exporte aucune fonction et n'a pas de manifeste. La DLL est livrée avec un fichier d'en-tête, expliquant comment l'utiliser. Le fichier d'en-tête définit d'innombrables structs, enums et une classe à construire en utilisant une méthode d'usine qui est accessible via une fonction Windows ::GetProcAddress (sécurité à travers obscurité). Cette classe contient les fonctions que j'aimerais utiliser dans le code managé.Est-il possible de marshaler matrice tableau natif à un tableau géré avec une boucle for

J'ai réussi à encapsuler la classe dans une classe de référence CLI et à y appeler des méthodes triviales, en les enveloppant également.

Je passe par le processus de conversion de certaines structures du fichier d'en-tête en structures gérées. Par exemple, struct autochtones:

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

Se transforme en struct géré:

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

Pour autant que je peux dire cela devrait rendre le blittable struct géré? Et toute autre structure qui suit un modèle similaire ou des niveaux de structure imbriquée. Tant qu'une mise en page est spécifiée et qu'aucun blittable n'est orné de MarshalAs, la structure dans son ensemble sera-t-elle blittable?

Et donc, je tente de voir s'il y a un moyen d'utiliser Marshal::Copy ou Marshal::PtrToStructure pour convertir un tableau FooACL*-array<ManagedFooACL>^.

Je reçois le tableau FooACL * à partir d'un appel de fonction; Je ne l'attribue pas moi-même.

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

total est une entrée/sortie qui obtient la taille du tableau retourné.

Ce que je réussi à faire jusqu'à présent, et ce travail est:

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

Ce que je ne peux pas envelopper mon esprit est autour de pourquoi cela ne:

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

Cela jette un: Y at-il un moyen de copier des données de tableau dans un appel ou ai-je vraiment besoin de faire une boucle for? Cela semble un peu idiot avec toute cette capacité de marshaling.

+0

Remarque: Si vous pouvez accéder à la fonction à l'aide de 'GetProcAddress', la fonction est exportée et peut être invoquée via pinvoke. –

+0

Je suis d'accord, mais ce n'est qu'une fonction d'usine qui me donne une classe qui contient la plupart des fonctionnalités que je recherche – Dmitry

+0

Bon, je ne voulais pas dire qu'il est pratique de le faire, juste en le notant pour référence future. :) –

Répondre

2

Après avoir fait d'autres recherches, il semble que la réponse est non. Il n'est pas possible de marshaler automatiquement un array de struct sans boucle.

Je pense que la principale raison pour laquelle marshalling travaille avec PtrToStructure est parce que la structure est statique/prédéfinie. Le compilateur sait comment disposer la mémoire. Depuis, vous obtenez une taille dynamique array il n'y a aucun moyen de spécifier la disposition de la mémoire à l'avance. Donc, vous devez boucler nombre dynamique de struct s.

Sinon, si vous saviez que vous serez toujours trouvé un tableau de longueur X, vous pouvez définir votre propre gestion struct tenant un élément, à savoir le tableau de ManagedFooACL avec une valeur ByValArray et SizeConst de X, et juste jeter le natif array au struct.

Questions connexes