C# C++ DLL passage du pointeur de pointeur en argument
Pourriez-vous les gars merci de m'aider à résoudre le problème suivant?
J'ai une fonction C++ dll, et il sera appelé par une autre application en C#.
L'une des fonctions dont j'ai besoin est le suivant:
struct DataStruct
{
unsigned char* data;
int len;
};
DLLAPI int API_ReadFile(const wchar_t* filename, DataStruct** outData);
J'ai écrit le code suivant en C#:
class CS_DataStruct
{
public byte[] data;
public int len;
}
[DllImport("ReadFile.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
private static extern int API_ReadFile([MarshalAs(UnmanagedType.LPWStr)]string filename, ref CS_DataStruct data);
Malheureusement, le code ci-dessus ne fonctionne pas... je suppose que c'est dû à la C++ func prend un pointeur de pointeur de DataStruct, alors que je viens de passer une référence de CS_DataStruct.
Mai je sais comment puis-je passer un pointeur de pointeur vers le C++ func? Si il n'est pas possible, est-il une solution de contournement? (de l'API C++ est fixe, de sorte qu'un changement de l'API de pointeur n'est pas possible)
Edit:
Mémoire de DataStruct sera alloué par la fonction c++. Avant cela, je n'ai aucune idée de la taille du tableau de données doit être.
(Merci pour les commentaires ci-dessous)
Vous devriez peut-être préciser davantage. Sera le code C++ allouer de la mémoire pour les données? Qui sera responsable de la désallocation de la mémoire? Vous pouvez également consulter la documentation de Microsoft sur le tableau de composition des trains:msdn.microsoft.com/en-us/library/z6cfh6e6%28v=vs.110%29.aspx. Je pense aussi que vous devriez utiliser struct au lieu de la classe en C#. struct est un type de valeur, tandis que la classe est un type de référence.
Comment libérer? Et je ne vois toujours pas une raison pour DataStruct**. Même en C++ uniquement, je suppose que l'appelant définir un DataStruct localement et passer le pointeur. Pas besoin de laisser API_ReadFile allouer de la mémoire pour la structure.
Attendez, n'est-ce pas un tableau de DataStruct? Si, vous n'avez probablement aucune option mais pour utiliser
unsafe
code ou C++/CLI. Vous avez accès au code source de API_ReadFile? Ou un exemple de code de l'utiliser en C++?Wu, la bibliothèque aussi fournir une API gratuit DataStruct, désolé de ne pas avoir mentionné dans la question. Je pense qu'il serait plus clair si le dernier paramètre est modifié pour "DataStruct*& outData". Mais de toute façon, c'est l'API et je ne peux pas changer
OriginalL'auteur LennonLam | 2013-12-06
Vous devez vous connecter pour publier un commentaire.
J'ai utilisé le test suivant la mise en œuvre:
Le code C# pour accéder à ces fonctions sont les suivantes:
Les données sont transférées à
buffer
en toute sécurité, et il devrait y avoir pas de fuites de mémoire. Je souhaite qu'il ne l'aide.Yongwei Wu - Une question ici, depuis le jeu de caractères Unicode, seul char n'est pas nécessairement une taille d'un octet, ai-je raison?
La taille de
char
est toujours la taille debyte
. Charset=Unicode signifie Système.La chaîne est classé en wchar_t* (au lieu de char*) par défaut. En fait Charset=Unicode ne doit avoir aucun effet ici, comme une chaîne de caractères est explicitement mobilisé comme UnmanagedType.LPWStr.OriginalL'auteur Yongwei Wu
Si vous faites appel code natif, assurez-vous que votre les structures sont alligned dans la mémoire. CLR alignement n'est pas garanti, sauf si vous pousser à.
Essayer
Plus d'infos:
http://www.developerfusion.com/article/84519/mastering-structs-in-c/
OriginalL'auteur Random
Il n'est pas nécessaire d'utiliser
unsafe
pour passer un pointeur vers un tableau à partir d'une DLL. Voici un exemple (voir les "résultats" de paramètre). La clé est d'utiliser leref
attribut. Il montre aussi comment passer plusieurs autres types de données.Tel que défini en C++/C:
Utilisé en C#:
Sans
extern "C"
partie, le compilateur C++ serait mangle le nom d'exportation dans un compilateur dépendant. J'ai remarqué que le point d'entrée /fonction Exportée nom correspond au nom de la fonction exactement dans un 64-bit DLL, mais il a un ajouté '@32' (le nombre peut varier) lors de la compilation dans une DLL 32 bits. Exécuterdumpbin /exports dllname.dll
pour trouver le nom exporté pour vous. Dans certains cas, vous pouvez aussi utiliser le DLLImport paramètreExactSpelling = true
. Notez que cette fonction est déclarée__stdcall
. Si elle n'a pas été précisé, il serait__cdecl
et vous auriez besoin deCallingConvention.Cdecl
.Ici est de savoir comment il peut être utilisé en C#:
OriginalL'auteur jtbr