Passage d'une classe C# de l'objet et de sortir d'une DLL C++ de la classe
J'ai travaillé sur un prototype de code de l'application qui s'exécute en C# et utilise des classes et des fonctions dans les plus anciens du code C++ (sous la forme d'une DLL importé). Le code exigence est de laisser un objet de classe pour le C++ DLL (à partir de C#) et il est être stockées/modifié pour l'extraction, plus tard, par l'application en C#. Voici le code que j'ai pour l'instant...
Simple DLL C++ de la Classe:
class CClass : public CObject
{
public:
int intTest1
};
C++ des Fonctions de la DLL:
CClass *Holder = new CClass;
extern "C"
{
//obj always comes in with a 0 value.
__declspec(dllexport) void SetDLLObj(CClass* obj)
{
Holder = obj;
}
//obj should leave with value of Holder (from SetDLLObj).
__declspec(dllexport) void GetDLLObj(__out CClass* &obj)
{
obj = Holder;
}
}
De Classe C# et Wrapper:
[StructureLayout(LayoutKind.Sequential)]
public class CSObject
{
public int intTest2;
}
class LibWrapper
{
[DLLImport("CPPDLL.dll")]
public static extern void SetDLLObj([MarshalAs(UnmanagedType.LPStruct)]
CSObject csObj);
public static extern void GetDLLObj([MarshalAs(UnmanagedType.LPStruct)]
ref CSObject csObj);
}
C# Appel de la Fonction de DLL:
class TestCall
{
public static void CallDLL()
{
...
CSObject objIn = new CSObject();
objIn.intTest2 = 1234; //Just so it contains something.
LibWrapper.SetDLLObj(objIn);
CSObject objOut = new CSObject();
LibWrapper.GetDLLObj(ref objOut);
MessageBox.Show(objOut.intTest2.ToString()); //This only outputs "0".
...
}
}
Rien, mais indésirable valeurs semblent être disponibles à l'intérieur de la DLL (venant du passé en C# de l'objet). Je crois que je suis absent quelque chose avec la classe de triage ou d'un mémoire/pointeur de la question. Ce qui me manque?
Edit:
J'ai changé le code ci-dessus pour refléter les changements apportés à la méthode/définition d'une fonction en C#/C++, suggéré par l'émission d'Obligations. La valeur (1234) transmis est récupéré par le code C# correctement maintenant. Cela a mis en évidence un autre problème dans la DLL C++. Le 1234 valeur n'est pas disponible pour le code C++. Au lieu que l'objet a une valeur de 0 à l'intérieur de la DLL. Je voudrais utiliser prédéfinis fonctions C++ pour modifier l'objet de l'intérieur de la DLL. Plus l'aide est grandement appréciée. Merci!
le Titulaire ne semblent être de stocker la valeur dans le code C++ pour la récupération plus tard. Je peux prendre un coup d'oeil, mais mon principal souci est maintenant de tirer une valeur à partir de l'objet passé dans la DLL.
OriginalL'auteur notsodev | 2012-06-20
Vous devez vous connecter pour publier un commentaire.
Bond était correct, je ne peux pas passer un objet entre gérés et non gérés code et encore ont-il conserver ses informations stockées.
J'ai juste appeler des fonctions C++ pour créer un objet et passez le pointeur de retour en C#'s IntPtr type. Je peux alors passer le pointeur autour de toute fonction C++ j'ai besoin (à la condition extern) à partir de C#. Ce n'était pas excatly ce que nous voulions faire, mais il servira son but dans la mesure où nous en avons besoin.
Ici C# wrapper je suis en utilisant par exemple ou de référence. (Note: je suis en utilisant StringBuilder au lieu de la 'int intTest" de mon exemple ci-dessus. C'est ce que nous voulions pour notre prototype. J'ai juste utilisé un nombre entier dans la classe de l'objet pour des raisons de simplicité.):
Bien sûr le C++ effectue toutes les modifications nécessaires et la seule façon pour C# pour accéder au contenu de l'est, plus ou moins, en demandant le contenu désiré par le biais de C++. Le code C# n'a pas accès à la unmanged contenu de classe de cette façon, le rendant un peu plus de code sur les deux extrémités. Mais, cela fonctionne pour moi.
C'est les références que j'ai utilisé pour la base de ma solution:
http://www.codeproject.com/Articles/18032/How-to-Marshal-a-C-Class
J'espère que cela peut aider certaines d'autres à économiser plus de temps que je n'ai essayer de le comprendre!
OriginalL'auteur notsodev
Je crois que vous devriez déclarer votre retour de méthode comme ceci
et, respectivement, le C# prototype
la entrant la méthode est un pointeur vers CClass trop, le C# prototype est ok.
Mon erreur, il doit être une référence de pointeur ou un pointeur de pointeur - j'ai corrigé mon code d'exemple. Vous devez utiliser une référence de pointeur dans votre getDLLObj et un pointeur dans la SetDLLObj et réparer votre C# prototype pour getDLLObj en ajoutant le mot-clé ref sur le paramètre.
Merci d'Obligations, vos suggestions qui ont permis à la suppression de la jonque valeurs stockées dans la DLL. Cependant, j'ai toujours mon problème d'une valeur de 0 est passée, où, comme il devrait être 1234. Croire il y a encore un problème entre le unmanged et de la mémoire gérée comme @user629926. Je vous remercie de votre aide et de tout autres pensées serait génial!
ce qui est indésirable exactement? l'obj intTest1 champ à l'intérieur de SetDLLObj(CClass obj)? pourriez vous s'il vous plaît mettre à jour votre question avec votre code actuel?
euh, je viens de voir cela, mais... tu ne peux pas juste maréchal un objet géré(CSObject) à un objet non géré(CClass) comme ceci. C'est juste ne va pas marcher, la mise en page est différente, votre CClass hérite de CObject... ah... je ne pense pas que ce soit possible, je pense que vous devriez utiliser COM pour cela, ou le C++(C++/CLI)
OriginalL'auteur Ventsyslav Raikov
Si vous utilisez la classe de C# ,vous devez utiliser GCHandle pour que http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.gchandle%28v=vs.110%29.aspx
edit:
Vous venez de remplacer CClass avec l'CClass* ou void* et vous pouvez l'utiliser comme IntPtr sur C# côté. Avez-vous de faire changer ses valeurs sur le C++? Aussi de classe C# CClass commissaires automatiquement comme CClass*. Vous petit plus ponctuellement essayer de déclarer votre classe en tant que structure et l'utilisation
public static extern void GetDLLObj( CSObject csObj);
Oui, je dois changer la valeur sur le C++ côté. Je suis en mesure d'obtenir la valeur 1234 passé sur le C#, côté (merci à @Bond), quand il revient, mais aucun changement, je cherche dans le code ne modifie pas le/retourne la valeur de l'objet. Je suis également toujours à l'affiche les objets de valeur 0 dans le code C++.
J'ai essayer de changer de classe C# pour un struct, mais il a produit quelques gares de problèmes. Pour une raison quelconque int intTest2 n'a pas pu être rassemblées pour le C++ homologue.
OriginalL'auteur user629926