🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: es.comp.os.linux.programacion
Article #11949

Re: Cargar librerías dinámicas sin estar presentes en tiempo de compilación.

#11949
From: J.A. Gutierrez
Date: Tue, 18 Sep 2001 14:13
395 lines
9548 bytes
Xavier Montero <xmontero@dsitelecom.com> wrote:
: Supongamos que quiero hacer un programa para Linux tal que
: a poisteriori de ser publicado la gente pueda desarrollar
: plugins para tal programa.


    Aqui tienes un exemplo, valido para bastantes unix y para
    windoze nt.
    Incluye rutinas para manejar plug-ins y al final, el codigo
    de ejemplo de un plug-in.

    No hay mucha documentacion, pero creo que el codigo es
    auto-explicativo...

---------------------------------------------------------------------------
/*
 * vpplug.h
 *
 * Manejo de Plug-ins (.dll en win32, .so en unix) para parametros
 * virtuales
 * Declaraciones comunes al programa principal y a los plug-in
 * spd@daphne.cps.unizar.es
 * Ultima modificacion: Sat Oct  4 23:12:26 GMT--1:00 1997
 */

#ifdef __cplusplus
extern "C" {
#endif

#define VPPLUGIN_MAIN   vp_plug-in_main
#define VPPLUGIN_MAGIC  vp_plug-in_magic
#define VPPLUGIN_MAGIC_VALUE    0x6969

#define VPPLUGIN_NAME               vp_plug-in_name
#define VPPLUGIN_MAX_NAME_LENGHT    32

#define VPFLOAT float

typedef VPFLOAT (* VP_PTR)(VPFLOAT,VPFLOAT,VPFLOAT);


#ifdef __cplusplus
}
#endif
---------------------------------------------------------------------------
/*
 * m_vpplug.h
 *
 * Manejo de Plug-ins (.dll en win32, .so en unix) para parametros
 * virtuales
 * spd@daphne.cps.unizar.es
 * Ultima modificacion: Sat Oct  4 23:12:26 GMT--1:00 1997
 */


#ifdef __cplusplus
extern "C" {
#endif

#define M_VPPATH    "MODEL_VPPATH"

#ifdef WIN32
#   define  PATH_SEP    '\\'
#   define  PATH_LIM    ";"
#   define  PLUG_EXT    ".dll"
#else
#   define  PATH_SEP    '/'
#   define  PATH_LIM    ":"
#   define  PLUG_EXT    ".so"
#endif

#define M_PLUG_ADD  10

#define M_PLUG_T_VP 0
#define M_PLUG_T_G  1

#define M_VPERR_NOERR   0
#define M_VPERR_NOPATH  1
#define M_VPERR_NOMEM   2
#define M_VPERR_BADPAR  3

typdef struct m_plug {
    int     type;
    char    *name;
    VP_PTR  *function;
    char    *path;
#ifdef WIN32
    HINSTANCE
#else
    void *
#endif
            lib;
    } M_PLUG;


/*
 * Globales
 */

extern M_PLUG *vp_plug;
extern unsigned vp_plug_idx;

/*
 * Prototipos
 */

extern int  m_vpplug_init(void);
extern int  m_vpplug_add(char *path, int which);
extern int  m_vpplug_reload(int which);
extern int  m_vpplug_free(int which);
extern int  m_vpplug_flush(void);



#ifdef __cplusplus
}
#endif
---------------------------------------------------------------------------
/*
 * m_vpplug.c
 *
 * Manejo de Plug-ins (.dll en win32, .so en unix) para parametros
 * virtuales
 * spd@daphne.cps.unizar.es
 * Ultima modificacion: Sat Oct  4 23:12:26 GMT--1:00 1997
 */


#include <stdio.h>
#include <stdlib.h>


#ifndef WIN32
#   include <sys/param.h>
#   include <sys/types.h>
#   if defined(DIRENT)
#       include <dirent.h>
        typedef struct dirent dir_type;
#   else
#       include <sys/dir.h>
        typedef struct direct dir_type;
#   endif
#   include <unistd.h>     /* chdir */
#   include <limits.h>
#   include <dlfcn.h>

#else
#   include <io.h>
#   include <time.h>
#   include <direct.h>

#   include <malloc.h>


#   ifdef MAXPATHLEN
#       undefine MAXPATHLEN
#   endif
#   define MAXPATHLEN _MAX_PATH

#   define getcwd _getcwd
#   define chdir _chdir
#endif


#include "vpplug.h"
#include "m_vpplug.h"

/*
 * Globales
 */

M_PLUG *vp_plug;
unsigned vp_plug_idx;


int m_vpplug_init(void);
{
    char *vppath, *path, *argt, po;
    char cwd[MAXPATHLEN];

    vp_plug_idx=0;
    vp_plug=NULL;

    if ((vppath=getenv(M_VPPATH))==NULL)
        return M_VPERR_NOPATH;

    if ((path = strdup(vppath))==NULL)
        return M_VPERR_NOMEM;

    if (getcwd(cwd, sizeof(cwd)) != NULL)
    {
        argt = strtok( path, PATH_LIM );
        while(argt!=NULL)
        {
            if ( -1 != chdir( argt ))
            {
#ifndef WIN32
                DIR         *dir;
                dir_type    *sd;
                char        *po;

                if ( NULL == (dir = opendir( "." )))
                {
                    perror("opendir");
                    continue;
                }
                else
                {
                    while ( NULL != ( sd = readdir( dir )))
                    {
                        po=strrchr(sd->d_name, '.');
                        if (
                            (po != NULL) &&
                            ( 0 == strcmp ( po, PLUG_EXT ))
                            )
                            if ( 0!= m_vpplug_add(sd->d_name,-1))
                                fprintf(stderr, "Can't load %s", sd->d_name);
                    }
                    closedir( dir );
                }
#else
                struct _finddata_t c_file;
                long hFile;

                /* Find first file in current directory */
                if( (hFile = _findfirst( "*"PLUG_EXT, &c_file )) == -1L )
                    continue;
                else
                {
                    do
                    {
                        if ( !( c_file.attrib & _A_SUBDIR ))
                        if ( 0!= m_vpplug_add(c_file.name,-1))
                            fprintf(stderr, "Can't load %s", c_file.name);
                    }
                    while( _findnext( hFile, &c_file ) == 0 );
                    _findclose( hFile );
                }
#endif
            }
            argt = strtok( NULL, PATH_LIM );
        }

        chdir(cwd);
    }
    else
        perror("getcwd");

    return M_VPERR_NOERR;
}


int m_vpplug_add(char *path, int which);
{
    int     result=M_VPERR_NOERR;
#ifndef WIN32
    void    *hLib;
#else
    HINSTANCE hLib;
#   define  dlsym   GetProcAddress
#endif
    char    **name;
    short   *magic;
    VP_PTR  fun;

    if (NULL==(hLib=
#ifndef WIN32
        dlopen(path, RTLD_NOW)
#else
        LoadLibrary( path )
#endif
        ))
        return 1;

    if ( which >= vp_plug_idx )
        return M_VPERR_BADPAR;

    if ( which < 0 )
        which = vp_plug_idx;

    if (!(
        (NULL==(magic=(short *)dlsym(hLib, VPPLUGIN_MAGIC))) ||
        ( *magic != VPPLUGIN_MAGIC_VALUE ) ||
        (NULL==(name=(char **)dlsym(hLib, VPPLUGIN_NAME))) ||
        (NULL==(fun=(VP_PTR)dlsym(hLib, VPPLUGIN_MAIN)))
        ))

    {
        if (( which == vp_plug_idx ) && ( vp_plug_idx % M_PLUG_ADD == 0))
            vp_plug = realloc ( vp_plug, sizeof(M_PLUG)*M_PLUG_ADD ));

        if ( vp_plug != NULL )
        {
            vp_plug[which].type=M_PLUG_T_VP;
            vp_plug[which].name=*name;
            vp_plug[which].function=fun;
            vp_plug[which].path=strdup(path);
            vp_plug[which].lib=hLib;
            if ( which == vp_plug_idx )
                ++vp_plug_idx;
        }
        else
            result=M_VPERR_NOMEM;
    }

    return result;
}

int m_vpplug_free(int which);
{
    vp_plug[which].function=NULL;
    if (vp_plug[which].path)
        free(vp_plug[which].path);

#ifndef WIN32
    dlclose(vp_plug[which].lib);
#else
    FreeLibrary(vp_plug[which].lib);
#endif


}
int m_vpplug_reload(int which);
{
    /* not implemented by now */
    return 1;
}

---------------------------------------------------------------------------

/*
 * Plug-in
 */

#include "vpplug.h"

/*
 * Identifica a esta libreria como plug-in valido
 */
EXPORT
short VPPLUGIN_MAGIC=VPPLUGIN_MAGIC_VALUE;


/*
 * Globales
 */

static int foo;

/*
 * Punto de entrada principal
 */
EXPORT
VPFLOAT VPPLUGIN_MAIN(VPFLOAT x, VPFLOAT min, VPFLOAT max)
{
    return ((x-min)*(VPFLOAT)90.0/(max-min));
}

/*
 * Inicializacion
 * Es llamado en la carga del modulo
 */
EXPORT
int VPPLUGIN_INIT(void)
{
    foo = not( foo );
    return 0;
}

/*
 * Eliminacion
 * Es llamado en la descarga del modulo
 */
EXPORT
int VPPLUGIN_FLUSH(void)
{
    return 0;
}

/*
 * Funciones locales
 * Deben ser static
 */
static int not (int i)
{
    return(!i);
}


---------------------------------------------------------------------------
-- 
PGP and other useless info at      \
http://www.cps.unizar.es/~spd/      \
finger://daphne.cps.unizar.es/spd    \       Timeo Danaos et dona ferentes
ftp://ivo.cps.unizar.es/pub/          \                         (Virgilio)   
Technical Details
Message-ID: <9o7kq3$q3n$1@news.unizar.es>
Path: arc1-ca.pugleaf.net!archiver1.google.com!newsfeed.google.com!sn-xit-02!supernews.com!isdnet!wanadoo.fr!opentransit.net!jussieu.fr!news.rediris.es!news.unizar.es!not-for-mail
References: <3BA3E2B3.40E8D8B9@dsitelecom.com>

Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: f86c8,26ed3f936bc3887b
X-Google-Attributes: gidf86c8,public
X-Google-ArrivalTime: 2001-09-18 06:54:18 PST
Path: arc1-ca.pugleaf.net!archiver1.google.com!newsfeed.google.com!sn-xit-02!supernews.com!isdnet!wanadoo.fr!opentransit.net!jussieu.fr!news.rediris.es!news.unizar.es!not-for-mail
From: "J.A. Gutierrez" <spd@daphne.cps.unizar.es>
Newsgroups: es.comp.os.linux.programacion
Subject: Re: Cargar librerías dinámicas sin estar presentes en  tiempo de compilación.
Date: 18 Sep 2001 14:13:23 GMT
Organization: Rank
Lines: 395
Message-ID: <9o7kq3$q3n$1@news.unizar.es>
References: <3BA3E2B3.40E8D8B9@dsitelecom.com>
NNTP-Posting-Host: daphne.cps.unizar.es
X-Trace: news.unizar.es 1000822403 26743 155.210.152.20 (18 Sep 2001 14:13:23 GMT)
X-Complaints-To: usenet@news.unizar.es
NNTP-Posting-Date: 18 Sep 2001 14:13:23 GMT
User-Agent: tin/1.4.5-20010409 ("One More Nightmare") (UNIX) (IRIX/6.2 (IP22))