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 :

Programmation COM en C


Sujet :

C

  1. #1
    Membre régulier
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Septembre 2016
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Finance

    Informations forums :
    Inscription : Septembre 2016
    Messages : 7
    Par défaut Programmation COM en C
    Bonjour,

    Je cherche à suivre un article de Jeff Glatt concernant la programmation COM en C : http://www.codeproject.com/Articles/...COM-in-plain-C

    Je ne vais pas très loin dans l'article avant d'avoir quelques difficultés. En fait tout va bien jusqu'à l'exemple de code 14, ou l'auteur décide que les fonctions doivent accéder aux membres "count" et "buffer" de la structure utilisée pour les appeler.
    Le compilateur n'accepte pas le code que j'ai tapé, ce qui ne m'étonne pas du tout car on référence des éléments non encore déclarés.

    Sauf que j'ai essayé de changer l'ordre des déclarations dans tous les sens, je référence toujours un élément qui est déclaré ensuite.

    Je ne vois pas comment on peut faire fonctionner tout cela.
    Pourriez-vous m'expliquer comment on doit faire, car si l'auteur réussis, ce doit donc venir de moi.

    Merci


    Code : 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
    44
    45
    46
    47
    48
    49
     
    /* Jeff Glatt COM in Plain C article #1
       error checking omited                */
    #include <Windows.h>
    #include <windef.h>
    #include <WinBase.h>
     
    typedef long SetStringPtr(IExample*, char *);
    typedef long GetStringPtr(IExample*, char *, long);
     
    typedef struct {
    	SetStringPtr *SetString;
    	GetStringPtr *GetString;
    } IExampleVtbl;
     
    typedef struct {
    	IExampleVtbl *lpVtbl;
    	DWORD count;
    	char buffer[80];
    } IExample;
     
    long SetString(IExample *this, char * str)
    {
    	return 0;
    }
     
    long GetString(IExample *this, char *buffer, long length)
    {
    	return 0;
    }
     
    int main(int argc, char **argv)
    {
    	static const IExampleVtbl IExample_Vtbl = { SetString, GetString };
    	IExample *example;
    	char *buffer;
     
    	example = (IExample *)GlobalAlloc(GMEM_FIXED, sizeof(IExample));
    	buffer = (char *)GlobalAlloc(GMEM_FIXED, 255);
     
    	example->lpVtbl = &IExample_Vtbl;
    	example->count = 0;
    	example->buffer[0] = 0;
     
    	long value1 = example->lpVtbl->SetString(example, "Some Texte");
    	long value2 = example->lpVtbl->GetString(example, buffer, 255);
     
    	return 0;
    }

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Réponse courte: Essaie en insérant struct IExemple; (pré-déclaration de structure sans la définir) entre les lignes 7 et 8.

    (la réponse longue est à venir)
    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
    Membre régulier
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Septembre 2016
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Finance

    Informations forums :
    Inscription : Septembre 2016
    Messages : 7
    Par défaut
    Merci pour votre réponse rapide.

    J'ai tenté votre proposition, en faisant quelques modification par ailleurs

    Code : 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
    44
    45
    46
    47
    48
    49
    /* Jeff Glatt COM in Plain C article #1
       error checking omited                */
    #include <Windows.h>
    #include <windef.h>
    #include <WinBase.h>
     
    struct _IExample;
    typedef long SetStringPtr(struct _IExample*, char *);
    typedef long GetStringPtr(struct _IExample*, char *, long);
     
    typedef struct {
    	SetStringPtr *SetString;
    	GetStringPtr *GetString;
    } IExampleVtbl;
     
    typedef struct _IExample {
    	IExampleVtbl *lpVtbl;
    	DWORD count;
    	char buffer[80];
    } IExample;
     
    long SetString(IExample *this, char * str)
    {
    	return 0;
    }
     
    long GetString(IExample *this, char *buffer, long length)
    {
    	return 0;
    }
     
    int main(int argc, char **argv)
    {
    	static const IExampleVtbl IExample_Vtbl = { SetString, GetString };
    	IExample *example;
    	char *buffer;
     
    	example = (IExample *)GlobalAlloc(GMEM_FIXED, sizeof(IExample));
    	buffer = (char *)GlobalAlloc(GMEM_FIXED, 255);
     
    	example->lpVtbl = &IExample_Vtbl;
    	example->count = 0;
    	example->buffer[0] = 0;
     
    	long value1 = example->lpVtbl->SetString(example, "Some Texte");
    	long value2 = example->lpVtbl->GetString(example, buffer, 255);
     
    	return 0;
    }
    Le programme se compile (VS 2015), et s'exécute bien en DEBUG.

    Les fonctions SetStringPtr() et GetStringPtr() étaient bien déclarée avant d'être définies, et, si je comprend bien, nous faisons la même chose avec la structure.

    Merci beaucoup de votre aide.
    Cdlt

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    C'est pas mal, en effet.
    En revanche:
    1. Tu n'es pas censé caster le retour de GlobalAlloc(). Si ça ne compile pas sans le cast, c'est que tu ne fais pas du vrai C, mais du "C sur un compilateur C++". Faire la différence entre C et C++ est extrêmement important pour la programmation COM, donc il ne faut surtout pas utiliser le mauvais compilateur: Assure-toi que l'extension de ton fichier est bien .c.
      • Et en fait, pourquoi appeler GlobalAlloc() plutôt que le bon vieux malloc()? Aucun de ces deux buffers n'est censé quitter le module (EXE ou DLL) courant (et pour le code moderne, CoTaskMemAlloc() est préférable de toute façon) ou passer dans des structures de données OLE qui exigent un HGLOBAL, donc le bon vieux malloc() suffirait...
      • Et pour aller plus loin, pourquoi utiliser l'allocation dynamique en premier lieu? Je peux comprendre pour l'objet lui-même (car ce sera nécessaire pour les vrais objets COM, qui utilisent un compteur de référence), mais là le buffer tiendrait largement dans la pile...
    2. Il est inhabituel sous Windows de déclarer des types "fonction" plutôt que des types "pointeur de fonction".
      Ce qu'on voit normalement sous Windows, c'est ceci:
      Code C : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      typedef long (*SetStringPtr)(struct _IExample*, char *);
      typedef long (*GetStringPtr)(struct _IExample*, char *, long);
       
      typedef struct {
      	SetStringPtr SetString;
      	GetStringPtr GetString;
      } IExampleVtbl;
      Mais évidemment, c'est juste une question de style. Sous le capot, les deux se valent.
    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.

  5. #5
    Membre régulier
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Septembre 2016
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Finance

    Informations forums :
    Inscription : Septembre 2016
    Messages : 7
    Par défaut
    Merci pour tes explications / remarques.

    Le fichier porte bien l'extension .c, de plus j'ai activé l'option /TC de VS.
    Pour ce qui est de l'utilisation de GlobalAlloc(), j'avoue avoir recopié bêtement l'exemple. Pour ma part, jusqu'à présent j'avais pour habitude d'utiliser HeapAlloc(). Je ne connais pas CoTaskMemAlloc(), une lecture en biais de la doc indique le la zone mémoire n'est pas initialisée, contrairement à ce que j'utilise comme option à HeapAlloc(). Je regarderais cela plus en détail un peu plus tard.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    #define MALLOC(x) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,x)
    #define REALLOC(ptr,x) HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,ptr,x)
    #define FREE(ptr) HeapFree(GetProcessHeap(),0,ptr)
    Dernière question le compilateur râle sur la ligne 41 du code de mon précédent post example->lpVtbl = &IExample_Vtbl; avec l'avertissement warning C4090: '=': different 'const' qualifiersJe ne comprend pas bien pourquoi.

    Merci
    Cordialement

  6. #6
    Membre Expert
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Par défaut
    Tu déclares IExample_Vtbl (nom de variable pas vraiment judicieux btw) const, &IExample_Vtbl est donc de type const IExampleVtbl * alors que tu essaies de l'assigner à une variable de type IExampleVtbl *.

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    La réponse est donc de le déclarer const dans la structure également.
    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 régulier
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Septembre 2016
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Finance

    Informations forums :
    Inscription : Septembre 2016
    Messages : 7
    Par défaut
    Parfait!

    Merci pour votre aide.

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

Discussions similaires

  1. Programme .com de lecture et d'affichage de chaîne
    Par mhaknet dans le forum x86 16-bits
    Réponses: 1
    Dernier message: 16/04/2009, 21h09
  2. [Débutant] Programme COM qui efface le curseur de souris
    Par le pythonien dans le forum x86 16-bits
    Réponses: 4
    Dernier message: 16/08/2008, 21h40
  3. [Programmation]Faire du COM/OLE sous Linux ou équivalence
    Par randriano dans le forum Applications et environnements graphiques
    Réponses: 13
    Dernier message: 12/06/2008, 08h51
  4. [DLL] Enregistrer DLL (COM) par programmation
    Par pataguillon dans le forum MFC
    Réponses: 5
    Dernier message: 14/03/2006, 14h01
  5. Lire et modifier un port com utilisé par un autre programme
    Par KBNOT-PRC600 dans le forum Langage
    Réponses: 5
    Dernier message: 12/02/2006, 17h40

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