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 une function


Sujet :

C

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Mars 2006
    Messages : 147
    Par défaut Exporter une function
    Bonjour à tous,

    J'ai écrit une fonction en C. Je souhaite maintenant pouvoir exporter cette fonction afin de pouvoir l'appeler depuis une autre programme écrit en Pascal.

    Je ne connais pas du tout C, et je n'ai donc aucune idée de la structure que doit avoir mon programme C.

    A ce stade, il compile et génère un exécutable (unix car je travaille sous Mac OS X). Dans mon programme Pascal, cet exécutable est bien trouvé lors du linkage. En revanche, si j'appelle ma fonction depuis mon programme Pascal, le compilateur renvoie cette erreur:

    Undefined symbols:
    "_GetBSDProcessListSimple", referenced from: _PC_GETPROCESS$TSTRINGLIST$$LONGINT in PC.o

    Voici le code si cela peut aider:
    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
     
    #include "mnifun.h"
    #include <assert.h>
    #include <errno.h>
    #include <stdbool.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <sys/sysctl.h>
     
     
    typedef struct  {
    	pid_t	p_pid;			/* Process identifier. */
    	char	p_comm[128]; 
    } procsimple;                   
     
    typedef struct kinfo_proc kinfo_proc;
     
    class TestLib
    {
    public:
    	int (procsimple ** proclistsimple, size_t *procCount);
    };
     
     
     
    int GetBSDProcessListSimple(procsimple ** proclistsimple, size_t *procCount)
    {
    	int err, i, j;
    	kinfo_proc *       process;
    	size_t             ProcCount;
     
        err = GetBSDProcessList(&process, &ProcCount);
    	*proclistsimple = (procsimple*)malloc(ProcCount * sizeof(procsimple));
    	for (i=0; i< ProcCount; i++) {
    		(*proclistsimple)[i].p_pid = process[i].kp_proc.p_pid;
    		for (j=0; j<MAXCOMLEN+1; j++) {
    			(*proclistsimple)[i].p_comm[j] = process[i].kp_proc.p_comm[j];
    		}
    	}			
    	free(process);
    	return err;
    };
    Comment déclarer proprement la fonction GetBSDProcessListSimple pour que je puisse l'importer depuis un autre programme (C ou Pascal) sachant que je souhaite que le linkage soit statique ?

    Merci d'avance,
    André.

    PS: Post initialement placé dans sous-forum .net par erreur.

  2. #2
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2010
    Messages : 6
    Par défaut
    Est-tu sûr de ton coup?
    Logiquement, compiler le pascal apres le C et tenter de faire référence à une fonction de l'exécutable C est...impossible, à moins que ta fonction C soit dans le main et ne fasse que ça. (et à moins que je ne me gourre complètement)

    Sinon, tu fais ça, tu pipe les programme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    prog1 [args] | prog2 [args]
    et tu fais en sorte que le C ne fasse que ta fonction par exemple avec un menu auquel repond le prog pascal (suffit d'ajouter le chiffre du menu avant tes variables).

    Par contre, c'est juste pour passer des variables... je vois pas comment faire autrement.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Mars 2006
    Messages : 147
    Par défaut
    Heu... Si tu veux, ce que je souhaite faire est ce qu'on ferait sous Windows en créant un DLL. Je crée ma DLL en C et j'appelle les fonctions de ma DLL depuis mon programme Pascal (ou n'importe quel autre langage d'ailleurs). Donc ça c'est possible parce que je l'ai déjà fait

    Ici, je ne suis pas sous windows, mais sous Mac OSX, et par commodité, pour ne pas à avoir à distribuer plusieurs fichiers, je souhaite faire une liaison statique et non dynamique.

  4. #4
    Rédacteur

    Avatar de ok.Idriss
    Homme Profil pro
    IS Consultant
    Inscrit en
    Février 2009
    Messages
    5 220
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : IS Consultant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2009
    Messages : 5 220
    Par défaut
    Bonsoir.

    Comme dit, je doute également que tu ne puisse faire autrement que ceci :

    - Tu appel ta fonction C dans la fonction main () en récupérant les paramètres de celle-ci (qui seront renseignés lors de l'exécution du programme).
    - Tu fait en sorte d'exécuter ton programme C en lui passant les paramètres depuis ton programme pascal ...

    Sinon, es-tu sûr que tu fait bien du C et pas du C++ ?

    Citation Envoyé par extrait de ton code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    class TestLib
    {
            public:    int (procsimple ** proclistsimple, size_t *procCount);
    };
    ça c'est pas du C ...

    Cordialement,
    Idriss

  5. #5
    Membre émérite Avatar de sloshy
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Janvier 2005
    Messages
    728
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Janvier 2005
    Messages : 728
    Par défaut
    Bonjour,
    La compilation est un ensemble d'outil et d'etape.
    Le but du jeu est de generer du code objet a partir de la source en C.
    Ensuite d'utiliser ce code objet lors de l'edition de lien dans le processus de compilation de la source pascal.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    hostname% gcc -c my_c.c
    hostname% pc -calign my_c.o my_pascal.p
    Voila, c'est tout

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Mars 2006
    Messages : 147
    Par défaut
    Citation Envoyé par ok.Idriss Voir le message
    Bonsoir.

    Comme dit, je doute également que tu ne puisse faire autrement que ceci :

    - Tu appel ta fonction C dans la fonction main () en récupérant les paramètres de celle-ci (qui seront renseignés lors de l'exécution du programme).
    - Tu fait en sorte d'exécuter ton programme C en lui passant les paramètres depuis ton programme pascal ...

    Sinon, es-tu sûr que tu fait bien du C et pas du C++ ?



    ça c'est pas du C ...

    Cordialement,
    Idriss
    Pour moi C, C++... j'avoue ne pas trop faire la nuance. C++ est objet (classes etc.) et pas C ? Peu importe pour moi s'il me faut faire C++ ou C.

    @ok.Idriss et @adcid : Je suis vraiment très surpris par vos réponses. Je NE VEUX PAS faire un programme C qui sera appelé par un programme PASCAL. Je veux faire ce que je fais tous les jours avec des bibliothèques C (C++ ???) existantes: du LINKING, dynamique ou statique. Comment pouvez-vous douter de la faisabilité de cette chose alors que c'est un principe de base ??? Je dois certainement mal m'exprimer:

    Quand je programme en Pascal ou en Progress (yet another language) sous windows, si j'ai besoin d'une fonction de l'API, ben je la prends via un linking dynamic, bref, je charge la DLL, et j'appelle la fonction qui m'intéresse. Ici, je veux faire exactement la même chose à deux détail prés:

    1. Je n'utilise pas un kernel32.dll ou autre mais mon propre code C
    2. Le linking doit être statique (donc fait lors de la compilation) puisque c'est mon propre code (donc ma librairie C ne sera pas sur l'ordinateur de mon voisin, il faut donc que je la lui livre, et je ne veux pas lui livrer 2 fichiers mais un seul)

    @sloshy
    Je comprends bien le processus de construction. Mais n'y a-t-il rien à faire au niveau du code en C (C++ ???) pour rendre la fonction exportable. Je m'explique: Quand on code une fonction, on n'a pas forcément envie que n'importe qui l'importe et l'utilise. En Pascal, on choisit donc explicitement ce qu'on souhaite rendre accessible. Lors de la phase d'édition des liens, seules les fonctions explicitement publiées sont accessibles.

    Dans l'exemple de la déclaration de la fonction GetBSDProcessListSimple, n'y a-t-il aucun mot clé à mettre spécifiquement pour dire au compilateur:

    "je souhaite que GetBSDProcessListSimple soit exportée au standard stdcall ou cdecl" ?

    Par ailleurs, es-tu sûr que le code objet d'un compilateur A est exploitable par un compilateur B ? Dans mon cas, je compile ma library C avec Xcode et je compile mon projet sous Lazarus/FPC. Ne dois-je pas plutôt générer un pur executable unix ?

    André

  7. #7
    Membre émérite Avatar de sloshy
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Janvier 2005
    Messages
    728
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Janvier 2005
    Messages : 728
    Par défaut
    Citation Envoyé par sinfoni Voir le message
    Pour moi C, C++... j'avoue ne pas trop faire la nuance. C++ est objet (classes etc.) et pas C ? Peu importe pour moi s'il me faut faire C++ ou C.
    Le C est un langage imperatif, le C++ est une modification du C pour que le langage soit oriente objet (ca fais beaucoup de difference).
    Les compilateurs actuelles sont capables de gerer les deux langages en un (comme sun et sa tablette ^^)


    Citation Envoyé par sinfoni Voir le message
    @ok.Idriss et @adcid : Je suis vraiment très surpris par vos réponses. Je NE VEUX PAS faire un programme C qui sera appelé par un programme PASCAL. Je veux faire ce que je fais tous les jours avec des bibliothèques C (C++ ???) existantes: du LINKING, dynamique ou statique. Comment pouvez-vous douter de la faisabilité de cette chose alors que c'est un principe de base ??? Je dois certainement mal m'exprimer:
    Non tu t'es bien exprime ...


    Citation Envoyé par sinfoni Voir le message
    Quand je programme en Pascal ou en Progress (yet another language) sous windows, si j'ai besoin d'une fonction de l'API, ben je la prends via un linking dynamic, bref, je charge la DLL, et j'appelle la fonction qui m'intéresse. Ici, je veux faire exactement la même chose à deux détail prés:

    1. Je n'utilise pas un kernel32.dll ou autre mais mon propre code C
    2. Le linking doit être statique (donc fait lors de la compilation) puisque c'est mon propre code (donc ma librairie C ne sera pas sur l'ordinateur de mon voisin, il faut donc que je la lui livre, et je ne veux pas lui livrer 2 fichiers mais un seul)
    C'est bien ce que ma solution propose


    Citation Envoyé par sinfoni Voir le message
    @sloshy
    Je comprends bien le processus de construction. Mais n'y a-t-il rien à faire au niveau du code en C (C++ ???) pour rendre la fonction exportable. Je m'explique: Quand on code une fonction, on n'a pas forcément envie que n'importe qui l'importe et l'utilise. En Pascal, on choisit donc explicitement ce qu'on souhaite rendre accessible. Lors de la phase d'édition des liens, seules les fonctions explicitement publiées sont accessibles.

    Dans l'exemple de la déclaration de la fonction GetBSDProcessListSimple, n'y a-t-il aucun mot clé à mettre spécifiquement pour dire au compilateur:

    "je souhaite que GetBSDProcessListSimple soit exportée au standard stdcall ou cdecl" ?
    Je comprend pas, tu as une fonction, tu crees un fichier objet de cette fonction, puis quand tu compiles ton programme pascale, tu lie le fichier objet ce qui aura pour but de faire un linkage statique et de placer ta fonction dans la table d'export, elle sera ainsi accessible partout et donc depuis ton code pascal, c'est ce que tu souhaites (?)
    Tu pourrais en C dire que ta fonction ne peut pas etre exportable (les fonctions statique a un fichier) et/ou les declarer dans un fichier header et inclure le fichier header dans certains fichiers C pour restreindre la portee de ta fonction, mais tu ne veux pas faire du C si? (j'avoue etre un peu perdu)

    Citation Envoyé par sinfoni Voir le message
    Par ailleurs, es-tu sûr que le code objet d'un compilateur A est exploitable par un compilateur B ? Dans mon cas, je compile ma library C avec Xcode et je compile mon projet sous Lazarus/FPC. Ne dois-je pas plutôt générer un pur executable unix ?

    André
    Je ne connais pas tous les compilateurs (a ne pas confondre avec les IDE) mais oui, tous les fichiers objets sont utilisables par tous les compilateurs (je dirais meme que c'est leur fonction premiere)
    puisqu'un fichier objet n'a plus de rapport avec la source de l'application (c'est un code binaire lie a l'OS et l'architecture).

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Mars 2006
    Messages : 147
    Par défaut
    Haaaa, je me suis bien exprimé... Ouf ! Non, je ne veux pas faire du C, mais juste me créer une librairie statique de fonctions C qui me permette de me simplifier la vie.

    Alors je vais mettre clairement un exemple, parce que comprendre la finalité aide souvent à comprendre tout court:

    Je réalise le portage d'une application que j'ai écrite pour Windows avec Delphi vers la plateforme Mac OSX avec compilateur = FPC et Ide=Lazarus.

    Depuis ce projet Pascal, j'ai besoin d'appeler des fonctions du noyau de l'OS (Tous les appels API Windows sont à réécrire par définition). Ca c'est facile, mais ça implique de créer en Pascal les structures équivalentes au C. Voici un exemple de structure pour une des fonctions qui m'interessent:

    La fonction: Elle liste les process
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int GetBSDProcessList(kinfo_proc **procList, size_t *procCount)
    Les structures utilisées par GetBSDProcessList:
    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
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
     
    struct extern_proc {
    	union {
    		struct {
    			struct	proc *__p_forw;	/* Doubly-linked run/sleep queue. */
    			struct	proc *__p_back;
    		} p_st1;
    		struct timeval __p_starttime; 	/* process start time */
    	} p_un;
    #define p_forw p_un.p_st1.__p_forw
    #define p_back p_un.p_st1.__p_back
    #define p_starttime p_un.__p_starttime
    	struct	vmspace *p_vmspace;	/* Address space. */
    	struct	sigacts *p_sigacts;	/* Signal actions, state (PROC ONLY). */
    	int	p_flag;			/* P_* flags. */
    	char	p_stat;			/* S* process status. */
    	pid_t	p_pid;			/* Process identifier. */
    	pid_t	p_oppid;	 /* Save parent pid during ptrace. XXX */
    	int	p_dupfd;	 /* Sideways return value from fdopen. XXX */
    	/* Mach related  */
    	caddr_t user_stack;	/* where user stack was allocated */
    	void	*exit_thread;	/* XXX Which thread is exiting? */
    	int		p_debugger;		/* allow to debug */
    	boolean_t	sigwait;	/* indication to suspend */
    	/* scheduling */
    	u_int	p_estcpu;	 /* Time averaged value of p_cpticks. */
    	int	p_cpticks;	 /* Ticks of cpu time. */
    	fixpt_t	p_pctcpu;	 /* %cpu for this process during p_swtime */
    	void	*p_wchan;	 /* Sleep address. */
    	char	*p_wmesg;	 /* Reason for sleep. */
    	u_int	p_swtime;	 /* Time swapped in or out. */
    	u_int	p_slptime;	 /* Time since last blocked. */
    	struct	itimerval p_realtimer;	/* Alarm timer. */
    	struct	timeval p_rtime;	/* Real time. */
    	u_quad_t p_uticks;		/* Statclock hits in user mode. */
    	u_quad_t p_sticks;		/* Statclock hits in system mode. */
    	u_quad_t p_iticks;		/* Statclock hits processing intr. */
    	int	p_traceflag;		/* Kernel trace points. */
    	struct	vnode *p_tracep;	/* Trace to vnode. */
    	int	p_siglist;		/* DEPRECATED */
    	struct	vnode *p_textvp;	/* Vnode of executable. */
    	int	p_holdcnt;		/* If non-zero, don't swap. */
    	sigset_t p_sigmask;	/* DEPRECATED. */
    	sigset_t p_sigignore;	/* Signals being ignored. */
    	sigset_t p_sigcatch;	/* Signals being caught by user. */
    	u_char	p_priority;	/* Process priority. */
    	u_char	p_usrpri;	/* User-priority based on p_cpu and p_nice. */
    	char	p_nice;		/* Process "nice" value. */
    	char	p_comm[MAXCOMLEN+1];
    	struct 	pgrp *p_pgrp;	/* Pointer to process group. */
    	struct	user *p_addr;	/* Kernel virtual addr of u-area (PROC ONLY). */
    	u_short	p_xstat;	/* Exit status for wait; also stop signal. */
    	u_short	p_acflag;	/* Accounting flags. */
    	struct	rusage *p_ru;	/* Exit information. XXX */
    };
    struct kinfo_proc {
            	struct	extern_proc kp_proc;			/* proc structure */
            	struct	eproc {
            		struct	proc *e_paddr;		/* address of proc */
            		struct	session *e_sess;	/* session pointer */
            		struct	_pcred e_pcred;		/* process credentials */
            		struct	_ucred e_ucred;		/* current credentials */
            		struct	 vmspace e_vm;		/* address space */
            		pid_t	e_ppid;			/* parent process id */
            		pid_t	e_pgid;			/* process group id */
            		short	e_jobc;			/* job control counter */
            		dev_t	e_tdev;			/* controlling tty dev */
            		pid_t	e_tpgid;		/* tty process group id */
            		struct	session *e_tsess;	/* tty session pointer */
            #define	WMESGLEN	7
            		char	e_wmesg[WMESGLEN+1];	/* wchan message */
            		segsz_t e_xsize;		/* text size */
            		short	e_xrssize;		/* text rss */
            		short	e_xccount;		/* text references */
            		short	e_xswrss;
            		int32_t	e_flag;
            #define	EPROC_CTTY	0x01	/* controlling tty vnode active */
            #define	EPROC_SLEADER	0x02	/* session leader */
            #define	COMAPT_MAXLOGNAME	12
            		char	e_login[COMAPT_MAXLOGNAME];	/* short setlogin() name */
            		int32_t	e_spare[4];
            	} kp_eproc;
            };
    Comme tu vois, la structure C est complexe, et convertir ce type de structure sous Pascal est un travail de gueux. Or, dans toute cette structure, seules 2 petites infos m'intéressent: le PID et le nom du Process.

    Je crée donc une fonction C (effectivement pas C++) qui s'occupe de l'appel à la fonction travaillant sur la structure complexe, et qui va copier dans une structure simplifiée créée par mes soins les 2 petites infos dont j'ai besoin:
    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
    int GetBSDProcessListSimple(procsimple ** proclistsimple, size_t *procCount)
    {
    	int err, i, j;
    	kinfo_proc *       process;
    	size_t             ProcCount;
     
        err = GetBSDProcessList(&process, &ProcCount);
    	*proclistsimple = (procsimple*)malloc(ProcCount * sizeof(procsimple));
    	for (i=0; i< ProcCount; i++) {
    		(*proclistsimple)[i].p_pid = process[i].kp_proc.p_pid;
    		for (j=0; j<MAXCOMLEN+1; j++) {
    			(*proclistsimple)[i].p_comm[j] = process[i].kp_proc.p_comm[j];
    		}
    	}			
    	free(process);
    	return err;
    };
    Voici la structure simplifié, aisément traductible en Pascal:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    typedef struct  {
    	pid_t	p_pid;			/* Process identifier. */
    	char	p_comm[128]; 
    } procsimple;
    Soit en Pascal pour info:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    p_proccount = ^cuint;
    procsimple = record
            p_pid: cuint;
            p_comm: array[0..127] of char; 
    end;
    p_procsimple = ^procsimple;
    pp_procsimple = ^p_procsimple;
    Donc sous XCode, je génère ma librairie, soit par exemple mylib.o. Et dans mes options de linking dans mon environnement Lazarus/FPC, j'indique le chemin d'accès à mylib.o. Mais lors de l'édition des liens, j'obtiens ce message:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Undefined symbols:
      "_GetBSDProcessListSimple", referenced from: _PC_GETPROCESS$TSTRINGLIST$$LONGINT in PC.o
    ld: symbol(s) not found
    Error: Error while linking
    Pourtant, si j'utilise mylib.o directement comme librairie dans xcode dans un projet de test en C, tout se passe bien. La construction trouve bien la fonction. Comme je connais très mal C, je dois sans doute faire une bêtise quelque part, mais je ne trouve pas du tout où

    Voici mes sources C:

    mylib.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    typedef struct kinfo_proc kinfo_proc;
     
    typedef struct  {
    	pid_t	p_pid;			/* Process identifier. */
    	char	p_comm[128]; 
    } procsimple;   
    int GetBSDProcessListSimple(procsimple ** proclistsimple, size_t *procCount);
    mylib.c
    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
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
     
    #include <assert.h>
    #include <errno.h>
    #include <stdbool.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <sys/sysctl.h>
    #include "mylib.h"
     
    // Ici static parce que je ne veux pas exporter cette fonction mais la suivante
    static int GetBSDProcessList(kinfo_proc **procList, size_t *procCount)
    // Returns a list of all BSD processes on the system.  This routine
    // allocates the list and puts it in *procList and a count of the
    // number of entries in *procCount.  You are responsible for freeing
    // this list (use "free" from System framework).
    // On success, the function returns 0.
    // On error, the function returns a BSD errno value.
    {
        int                 err;
        kinfo_proc *        result;
        bool                done;
        static const int    name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 };
        // Declaring name as const requires us to cast it when passing it to
        // sysctl because the prototype doesn't include the const modifier.
        size_t              length;
     
        assert( procList != NULL);
        assert(*procList == NULL);
        assert(procCount != NULL);
     
        *procCount = 0;
     
        // We start by calling sysctl with result == NULL and length == 0.
        // That will succeed, and set length to the appropriate length.
        // We then allocate a buffer of that size and call sysctl again
        // with that buffer.  If that succeeds, we're done.  If that fails
        // with ENOMEM, we have to throw away our buffer and loop.  Note
        // that the loop causes use to call sysctl with NULL again; this
        // is necessary because the ENOMEM failure case sets length to
        // the amount of data returned, not the amount of data that
        // could have been returned.
     
        result = NULL;
        done = false;
        do {
            assert(result == NULL);
     
            // Call sysctl with a NULL buffer.
     
            length = 0;
            err = sysctl( (int *) name, (sizeof(name) / sizeof(*name)) - 1,
    					 NULL, &length,
    					 NULL, 0);
            if (err == -1) {
                err = errno;
            }
     
            // Allocate an appropriately sized buffer based on the results
            // from the previous call.
     
            if (err == 0) {
                result = (kinfo_proc*)malloc(length);
                if (result == NULL) {
                    err = ENOMEM;
                }
            }
     
            // Call sysctl again with the new buffer.  If we get an ENOMEM
            // error, toss away our buffer and start again.
     
            if (err == 0) {
                err = sysctl( (int *) name, (sizeof(name) / sizeof(*name)) - 1,
    						 result, &length,
    						 NULL, 0);
                if (err == -1) {
                    err = errno;
                }
                if (err == 0) {
                    done = true;
                } else if (err == ENOMEM) {
                    assert(result != NULL);
                    free(result);
                    result = NULL;
                    err = 0;
                }
            }
        } while (err == 0 && ! done);
     
        // Clean up and establish post conditions.
     
        if (err != 0 && result != NULL) {
            free(result);
            result = NULL;
        }
        *procList = result;
        if (err == 0) {
            *procCount = length / sizeof(kinfo_proc);
        }
     
        assert( (err == 0) == (*procList != NULL) );
     
    	return err;
    }
     
    // Ici pas static pour autoriser l'export 
    int GetBSDProcessListSimple(procsimple ** proclistsimple, size_t *procCount)
    {
    	int err, i, j;
    	kinfo_proc *       process;
    	size_t             ProcCount;
     
        err = GetBSDProcessList(&process, &ProcCount);
    	*proclistsimple = (procsimple*)malloc(ProcCount * sizeof(procsimple));
    	for (i=0; i< ProcCount; i++) {
    		(*proclistsimple)[i].p_pid = process[i].kp_proc.p_pid;
    		for (j=0; j<MAXCOMLEN+1; j++) {
    			(*proclistsimple)[i].p_comm[j] = process[i].kp_proc.p_comm[j];
    		}
    	}			
    	free(process);
    	return err;
    };
    Voilà...
    Maintenant, si je construis le programme C suivant:
    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
     
    #include <stdio.h>
    #include <assert.h>
    #include <errno.h>
    #include <stdbool.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <sys/sysctl.h>
    #include "mylib.h"
     
    extern int  GetBSDProcessListSimple(procsimple ** proclistsimple, size_t *procCount);
     
    int main (int argc, const char * argv[]) {
     
     
    	procsimple * proc;
    	size_t procCount;
     
    	GetBSDProcessListSimple(&proc, &procCount);
     
        // insert code here...
        printf("Hello, World!\n");
        return 0;
    }
    ...ça compile. Attention, je sais bien que ce prog ne tournera pas, il n'y a pas d'allocation de la mémoire etc. Mais l'exécutable Unix est généré, il se lance et ... m'insulte. Mais la fonction GetBSDProcessListSimple est bien appelée.

    Si tu as d'autres questions, n'hésite pas !

    André.

  9. #9
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Mars 2006
    Messages : 147
    Par défaut
    C'est bon... L'erreur était la suivante: le fichier .o contenant ma fonction C était généré pour une plateforme différente... Il me fallait juste préciser I386 au niveau compilation.

    Détail pas inintéressant du tout: Lorsque je suis en mode pas à pas, mon débugger me permet de débugger aussi le source C : Le source s'affiche comme si c'était du pascal et je peux exécuter le C instruction par instruction depuis mon IDE Lazarus, que du bonheur

    Pour ceux que ça intéresse, document décrivant bien la chose ici:

    ftp://ftp.freepascal.org/pub/fpc/doc...FreePascal.pdf

    Merci à sloshy qui m'a conforté dans l'idée que la chose était possible.

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

Discussions similaires

  1. aide pour exporter une base de donnée
    Par matt55 dans le forum PostgreSQL
    Réponses: 8
    Dernier message: 06/04/2004, 14h28
  2. [phpPgAdmin] Exporter une base entière ?
    Par ovh dans le forum PostgreSQL
    Réponses: 2
    Dernier message: 01/01/2004, 18h21
  3. tbitmap.free dans une function
    Par portu dans le forum Langage
    Réponses: 7
    Dernier message: 19/06/2003, 22h08
  4. Réponses: 4
    Dernier message: 07/12/2002, 07h34

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