Comment puis-je marshall un pointeur vers un pointeur d'un tableau de structures?
Mon C déclarations sont comme suit:
int myData(uint myHandle, tchar *dataName, long *Time, uint *maxData, DATASTRUCT **data);
typedef struct {
byte Rel;
__int64 Time;
char Validated;
unsigned char Data[1];
} DATASTRUCT ;
Mon C# déclarations sont comme suit:
[DllImport("myData.dll", EntryPoint = "myData")]
public static extern int myData(uint myHandle, [MarshalAs(UnmanagedType.LPTStr)] string dataName, out long Time, out uint maxData, ref DATASTRUCT[] data);
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct DATASTRUCT
{
public sbyte Rel;
public long Time;
public byte Validated;
public double Data;
}
Je puis appeler la fonction managée comme suit:
string dataToShow = "description";
long Time;
uint maxData; //How many structs will be returned, i.e. how much data is available
uint myHandle = 1;
DATASTRUCT[] dataInformation = new DATASTRUCT[3]; //doesn't matter what I specify as the array size?
myData(myHandle, dataToShow, out Time, out maxData, ref dataInformation);
Lors de l'exécution de la fonction ci-dessus sera de retour avec succès avec seulement une structure, même si il ya 3 pour revenir. Pourquoi est-ce donc?
Des informations supplémentaires; j'ai essayé de passer le pointeur vers un pointeur d'un tableau de struct l'une des manières suivantes:
- ref DATASTRUCT[] data; //Works but only returns one struct
- [Out, MarshalAs(UnmanagedType.LPArray)] DATASTRUCT[] data; //returns the number of defined structs with garbage
Si je comprends bien j'ai peut-être besoin de faire de manuel de triage à l'aide de IntPtr
, je ne sais pas comment implémenter cela, cependant, donc, tous les conseils seront les bienvenues.
Quelle est la fonction C l'allocation de leurs structures? Faut-il utiliser le tableau d'entrée comme un tampon, ou de générer de nouvelles structures avec malloc?
Oh, et aussi, vous êtes en C# déclaration des regards mauvais. Un unsigned char n'est pas de la même taille que d'un lit double (1 vs 8 octets)
Malheureusement, la bibliothèque DLL de la documentation ne précise pas si il alloue de la mémoire pour la structure ou pas. Je suis en supposant qu'elle ne l'est pas. Je ne vous donnent pas la pleine décélération pour
Essayez cette [, MarshalAs(UnmanagedType.LPArray,SizeParamIndex:=3)] DATASTRUCT[] data;
J'obtiens une exception lors de l'appel de ce que
Oh, et aussi, vous êtes en C# déclaration des regards mauvais. Un unsigned char n'est pas de la même taille que d'un lit double (1 vs 8 octets)
Malheureusement, la bibliothèque DLL de la documentation ne précise pas si il alloue de la mémoire pour la structure ou pas. Je suis en supposant qu'elle ne l'est pas. Je ne vous donnent pas la pleine décélération pour
Data
c'est en fait une variable char qui peut prendre un maximum de 8 octets et c'est la raison derrière le marshaling comme un double, cette variable certainement renvoie des résultats corrects à chaque fois que je l'ai testé.Essayez cette [, MarshalAs(UnmanagedType.LPArray,SizeParamIndex:=3)] DATASTRUCT[] data;
J'obtiens une exception lors de l'appel de ce que
myData(myHandle, dataToShow, out Time, out maxData, out dataInformation);
retrait de la out
retourne un résultat similaire comme [Out, MarshalAs(UnmanagedType.LPArray)] DATASTRUCT[] data;
OriginalL'auteur user1470994 | 2012-06-21
Vous devez vous connecter pour publier un commentaire.
Bon, il semble que votre propre bibliothèque de l'allocation, si vraiment tout ce que vous devez faire est de fournir un pointeur à travers laquelle vous pouvez accéder aux données allouées.
Changer votre définition de l'API (remarque, j'ai changé le maxData param pour uint, long de 64 bits .NET et 32 bits en natif.
Sur le dessus de ma tête, je ne me souviens pas si vous avez besoin de la sortir de mot-clé pour le dernier paramètre, mais je pense que oui.
Ensuite, appelez myData:
Maintenant, pAllocs doit pointer vers une mémoire non managée, maréchal de ces gérés de la mémoire n'est pas trop difficile:
Et maintenant, vous devriez avoir un ensemble de locaux des structures.
Un point à noter
Vous devrez peut-être configurer votre projet pour compiler que les x86, de normaliser la taille d'un IntPtr à 4 octets (DWORD) au lieu de AnyCPU par défaut de 8.
public IntPtr Data;
les données renvoyées pourdata
semble comme des ordures, si je change de nouveau àpublic double Data;
il renvoie les données correctement.OriginalL'auteur Jason Larke
Un pointeur vers un pointeur peut être représenté dans votre dllimport déclaration ref IntPtr de données, de sorte que votre déclaration devient:
(En aparté, je pense qu'un long C est juste l'équivalent d'un int en C#. Longtemps en C# est un Int64, ce qui serait un long long en C)
Rassemblement de la DATASTRUCT[] pour un IntPtr peut être fait en utilisant le GCHandle classe
En utilisant le Maréchal de la classe et de la StructureToPtr ou méthodes de Copie de ce serait aussi une option, mais pour les besoins de la preuve du concept au moins le GCHandle devrait faire l'affaire, il n'est tout simplement pas idéal pour les scénarios où le code non managé n'long de l'exécution d'opérations parce que vous avez épinglé cet objet en place et que le GC ne peut pas le déplacer jusqu'à ce que vous gratuit.
Avez-vous mis à jour le c# struct définition trop? La unsigned char à l'origine, ne serait pas se traduire par un double @JasonLarke observée dans les autres commentaires. Si vous obtenez la taille de la structure est-elle adaptée à la taille attendue par le code C?
Il pourrait être la peine d'essayer Maréchal et juste en passant un pointeur vers un pointeur vers un tableau de tableaux d'octets au lieu d'un tableau de DATASTRUCTS. Au moins, alors vous devriez être en mesure de voir s'il y a des octets à tous.
Oui, j'ai aussi mis à jour la structure, la
unsigned char Data[1];
est le retour des valeurs correctes, je crois. Comment puis-je vérifier que le courant struct la taille correspond le code C? Comme je l'ai dit il y a certainement des données qu'il renvoie 1 struct ok lors de l'utilisation deref DATASTRUCT[] data;
En C# Maréchal.SizeOf(typeof(DATASTRUCT)) va vous donner la taille en octets requis pour l'ensemble de la structure. Je ne sais pas comment vous pouvez obtenir que, dans C, probablement juste de calculer manuellement à partir de la définition. Je le fais 7 octets dans le code C.
OriginalL'auteur Nanhydrin