IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Exporter string c++


Sujet :

C++

  1. #1
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2014
    Messages
    89
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2014
    Messages : 89
    Points : 52
    Points
    52
    Par défaut Exporter string c++
    Bonjour à tous,

    Je suis débutant en c++, et j aimerais exporter à partir d'une dll c++ un string ou char.

    Le code en lui même ouvré un fichier texte au et recopie son contenu dans la variable char.

    Une fonction getText permet de retourner le char
    Cette fonction est exporté dans la dll

    Lorsque j appelle la dll sous vs en c# je n arrive pas a recuperer le texte.

    Pouvez vous m aider ?

    apercu code c++

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    char getText()
    {
         char c[10]; //char[0]=a....char[10]=k
         return c[10];
    }
    apercu code C#:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
            public static extern char getText();
            static void Main(string[] args)
            {
     
     
                charresult = getText();
     
                Console.ReadKey();
            }

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Si tu veux retourner une chaîne de caractères char d'une manière utilisable depuis le C#, le plus simple est de retourner une chaîne allouée avec CoTaskMemAlloc() (obtenue en incluant <windows.h>):
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #include <windows.h>
    #include <strsafe.h>
     
    char* getText()
    {
    	char * txt = CoTaskMemAlloc(10);
    	if(txt == NULL)
    		return NULL; /*Echec*/
    	StringCchCopy(txt, 10, "toto");
    	return txt;
    }
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    using System.Runtime.InteropServices;
     
    class MaClasse
    {
    	//Le premier attribut signale une fonction dans ta DLL, 
    	//	avec la convention d'appel C (vu qu'elle n'est pas déclarée __stdcall),
    	//	et dont les chaînes de caractères sont constituées de char (et non pas de wchar_t).
    	//Le second attribut signale qu'elle retourne une chaîne allouée avec CoTaskMemAlloc()
    	//	Le framework .Net s'occupera de convertir la chaîne en System::String, et d'appeler CoTaskMemFree().
    	[DllImport("madll.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi)]
    	[return: MarshalAs(UnmanagedType.LPStr)]
    	extern static string getText();
    }
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Ah, vu que tu es en C++, il faudra déclarer ta fonction en extern "C". Et une fonction de conversion de std::string en chaîne utilisable devrait t'être utile aussi:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    #include <windows.h>
    #include <strsafe.h>
    #include <string>
     
    //Définit une macro EXTERN_C pour gestion facilitée
    #ifndef EXTERN_C
    #ifdef __cplusplus
    #define EXTERN_C extern "C"
    #else
    #define EXTERN_C extern
    #endif
    #endif
     
    char* CoTaskMemAllocFromString(std::string const &str)
    {
    	size_t bufferSize = str.length() + 1;
    	char* ret = CoTaskMemAlloc(bufferSize);
    	if(ret == NULL)
    		return NULL; //Echec
    	StringCchCopy(ret, bufferSize, str.c_str());
    	return ret;
    }
     
    EXTERN_C char* getText()
    {
    	std::string str = "toto";
    	str += "titi";
    	char * txt = CoTaskMemAllocFromString(str);
    	return txt;
    }
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  4. #4
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2014
    Messages
    89
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2014
    Messages : 89
    Points : 52
    Points
    52
    Par défaut
    je suis parvenu à récuperer toto en string depuis vs sous c#.

    Maintenant j'aimerais faire la même chose avec une chaine de caractère, cad récuperer en c# une chaine renvoyé par la dll c++, c'est possible ?

  5. #5
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2014
    Messages
    89
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2014
    Messages : 89
    Points : 52
    Points
    52
    Par défaut
    très compliqué tout ça :S

    J'ai réussi à stocker un xml dans un char[1000]
    Mais impossible de le récupérer dans mon code c#, j'obtiens parfois des caractères incompréhensibles

    exemple de xml:

    Code xml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <?xml version="1.0" encoding="utf-8"?>
    <root>
      <title>Some Title</title>
      <description>Some description</description>
      <keywords>
        <keyword>Keyword1</keyword>
        <keyword>Keyword2</keyword>
        <keyword>Keyword3</keyword>
        <keyword>Keyword4</keyword>
       </keywords> 
    </root>

    valeur de char[100]:


    char[0] = <
    char[1] = ?
    char[2] =x...

  6. #6
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Dans ce cas, il faudrait plutôt le transmettre comme tableau d'octets, mais pour avoir la longueur avec, ce n'est pas évident (à moins d'utiliser un SAFEARRAY, qui est loin d'être trivial à utiliser).

    Sinon, tu pourrais convertir la chaîne UTF-8 en UTF-16 depuis le C avec la fonction MultiByteToWideChar(), retournant ainsi au C# une chaîne de wchar_t (voire une BSTR, qui est un autre type accepté par C#) qui n'aurait pas de soucis de conversion.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Voici des fonctions pour convertir une zone mémoire en SAFEARRAY d'octets ou pour convertir une chaîne de caractères en BSTR:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    #include <windows.h>
     
    BSTR BstrFromChars(const char *strA, int codePage)
    {
    	/*MultiByteToWideChar returns a size that includes the NUL terminator*/
    	int cchWideSize = MultiByteToWideChar(codePage, 0, strA, -1, NULL, 0);
    	int cchWideLength = cchWideSize - 1;
    	BSTR bstrRet;
    	if(cchWideSize == 0) { return NULL; }
     
    	/*SysAllocStringLen() takes care of adding the NUL terminator */
    	bstrRet = SysAllocStringLen(NULL, cchWideLength);
    	if(bstrRet == NULL) { return NULL; }
     
    	MultiByteToWideChar(codePage, 0, strA, -1, bstrRet, cchWideSize);
    	return bstrRet;
    }
     
     
    SAFEARRAY* MakeSafeArrayOfBytes(const void *mem, unsigned int size) /*Sorry, safe arrays don't accept a size_t*/
    {
    	SAFEARRAY* pRet = SafeArrayCreateVector(VT_UI1, 0, size);
    	BOOL bSuccess = FALSE;
    	if(pRet != NULL)
    	{
    		void* pSafeArrayData;
    		if(SUCCEEDED(SafeArrayAccessData(pRet, &pSafeArrayData)))
    		{
    			memcpy(pSafeArrayData, mem, size);
    			SafeArrayUnaccessData(pRet);
    			bSuccess = TRUE;
    		}
    	}
     
    	/*If it failed, clean up*/
    	if(!bSuccess)
    	{
    		SafeArrayDestroy(pRet);
    		pRet=NULL;
    	}
     
    	return pRet;
    }
    Pour la BSTR, la valeur de codePage qui t'intéresse sera CP_UTF8.

    Après, côté C# ça ne devrait pas être un gros problème: Une BSTR, c'est juste une System.String avec UnmanagedType.BStr dans l'attribut MarshalAs, et un safeArray de bytes c'est un byte[] avec UnmanagedType.SafeArray et SafeArraySubType=VarEnum.VT_UI1.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  8. #8
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2014
    Messages
    89
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2014
    Messages : 89
    Points : 52
    Points
    52
    Par défaut
    merci pour ta solution j'ai essayé de l'intégré dans mon code mais ce n'est pas évident pour moi.

    Pourrai tu me donner un exemple avec la chaine

    char[0]=t
    char[1]=0
    char[2]=t
    char[3]=0

    merci !!!!!!!!!

  9. #9
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    OK, mais juste pour être sûr qu'on est sur la même page, je vais d'abord résumer le problème:
    1. Tu as une fonction C (ou C++) native qui doit retourner une chaîne de char à un code C#.
    2. Cette chaîne est encodée en UTF-8, ce qui fait que la procédure mentionnée au message #2 n'est pas appropriée (car elle marche pour un texte encodé en Windows-1252).

    Pour résoudre ce problème, il y a deux solutions:
    • Retourner directement le texte UTF-8 sous forme d'un tableau de bytes, et laisser le code C# convertir depuis UTF-8 vers une String C#.
    • Faire la conversion de UTF-8 vers une chaîne de wchar_t du côté du code C (ou C++) natif, et le retourner au code C# sous forme:
      • soit d'un tableau de wchar_t alloué avec CoTaskMemAlloc()
      • soit d'une BSTR

    Je vais à présent montrer les deux solutions. Dans le cas de la seconde solution, ayant déjà montré la solution du tableau alloué par CoTaskMemAlloc(), je vais montrer la solution BSTR.


    Solution 1: Retourner un tableau de bytes
    Pour ça, il faut se servir de la fonction MakeSafeArrayOfBytes() pour retourner un SAFEARRAY:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    EXTERN_C SAFEARRAY* getText()
    {
    	const char * chaine = "toto";
    	/* Une chaîne retournée au C# sous forme d'un tableau de bytes
    	n'a pas besoin de caractère nul terminal. */
    	SAFEARRAY * pRet = MakeSafeArrayOfBytes(chaine, strlen(chaine));
    	return pRet;
    }
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    using System.Runtime.InteropServices;
     
    class MaClasse
    {
    	//Le premier attribut signale une fonction dans ta DLL, 
    	//	avec la convention d'appel C (vu qu'elle n'est pas déclarée __stdcall),
    	//Le second attribut signale qu'elle retourne un SAFEARRAY de bytes
    	//	Le framework .Net s'occupera de convertir le SAFEARRAY en byte[], et d'appeler SafeArrayDestroy().
    	//	Mais il ne s'occupera pas de convertir le byte[] en String, c'est au code appelant de le faire.
    	[DllImport("madll.dll", CallingConvention=CallingConvention.Cdecl)]
    	[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VarEnum.VT_UI1)]
    	private extern static byte[] getText();
     
    	public string GetText()
    	{
    		byte[] bytes = getText();
    		//Utilise Encoding.UTF8 pour faire la conversion
    		return System.Text.Encoding.UTF8.GetString(bytes);
    	}
    }


    Solution 2: Retourner une BSTR
    Pour ça, il faut se servir de la fonction BstrFromChars() pour retourner une BSTR:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    EXTERN_C BSTR getText()
    {
    	char const * chaine = "toto";
    	BSTR pRet = BstrFromChars(chaine, CP_UTF8);
    	return pRet;
    }
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    using System.Runtime.InteropServices;
     
    class MaClasse
    {
    	//Le premier attribut signale une fonction dans ta DLL, 
    	//	avec la convention d'appel C (vu qu'elle n'est pas déclarée __stdcall),
    	//Le second attribut signale qu'elle retourne une BSTR
    	//	Le framework .Net s'occupera de convertir la chaîne en System::String, et d'appeler SysFreeString().
    	[DllImport("madll.dll", CallingConvention=CallingConvention.Cdecl)]
    	[return: MarshalAs(UnmanagedType.BStr)]
    	extern static string getText();
    }
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  10. #10
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2014
    Messages
    89
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2014
    Messages : 89
    Points : 52
    Points
    52
    Par défaut
    je ne trouve pas la fonction "MakeSafeArrayOfBytes" :s pourrais tu me dire dans quelle bibliothèque elle se trouve

    lorsque j'essaye la solution 1 proposé sans la fonction "MakeSafeArrayOfBytes": j'ai le message d'erreur lors de la recuperation du string:
    SafeArray of rank 56856 has been passed to a method expecting an array of rank 1.

  11. #11
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Elle est dans le message #7.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  12. #12
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2014
    Messages
    89
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2014
    Messages : 89
    Points : 52
    Points
    52
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Elle est dans le message #7.
    j'essaye de suite

  13. #13
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2014
    Messages
    89
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2014
    Messages : 89
    Points : 52
    Points
    52
    Par défaut
    ça marche nikel !!!!!!!!!!
    je vais essayé de comprendre le code maintenant !
    merci de ton aide !

  14. #14
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    N'hésite pas à poser des questions sur les parties que tu ne comprends pas.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 4
    Dernier message: 22/07/2011, 09h33
  2. PB export string 250 ->(MEMO)
    Par AODRENN dans le forum Bases de données
    Réponses: 1
    Dernier message: 14/06/2007, 09h16
  3. Réponses: 1
    Dernier message: 22/08/2002, 17h00
  4. String Grid et choix d'une couleur pour une ligne
    Par Gigottine dans le forum C++Builder
    Réponses: 12
    Dernier message: 17/05/2002, 15h23
  5. [CR] exporter en PDF
    Par Nathy dans le forum SAP Crystal Reports
    Réponses: 3
    Dernier message: 16/05/2002, 09h27

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo