Article View: es.comp.os.linux.programacion
Article #11949Re: Cargar librerías dinámicas sin estar presentes en tiempo de compilación.
From: J.A. Gutierrez
Date: Tue, 18 Sep 2001 14:13
Date: Tue, 18 Sep 2001 14:13
395 lines
9548 bytes
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-mailReferences:
<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))