FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

function plugins, e.g. "import f(x) from 'plugin.so'" · gnuplot/gnuplot@30e021b · GitHub

Repository navigation

Commit 30e021b

Browse files
Ethan A Merritt
committed
function plugins, e.g. "import f(x) from 'plugin.so'"
1 parent 02f0225 commit 30e021b

20 files changed

Lines changed: 759 additions & 23 deletions

‎ChangeLog‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
2014-02-27 Ethan A Merritt <merritt@u.washington.edu>
2+
3+
* src/command.c src/command.h src/eval.c src/eval.h src/external.c
4+
src/external.h src/gp_types.h src/Makefile.am src/show.c src/tables.c:
5+
New command `import func(x) from "sharedobject"` extends gnuplot
6+
expresssion evaluation to allow calling functions exported by an
7+
external shared object (a.k.a. plugins).
8+
- original patch 2002 Stephan Boettcher <boettcher@physik.uni-kiel.de>
9+
- updated for 4.7 2014 Alexander Täschner <taschna@users.sf.net>
10+
- revised syntax and error handling 2014 Ethan A Merritt
11+
12+
* config/config.nt configure.in demo/Makefile.am.in:
13+
./configure --disable-plugins [enabled by default]
14+
15+
* demo/plugin/demo_plugin.c demo/plugin/gnuplot_plugin.h
16+
demo/plugin/Makefile demo/plugin/plugin.dem docs/gnuplot.doc:
17+
Template files demonstrating the creation of custom plugin libraries.
18+
119
2014-02-27 Bastian Maerkisch <bmaerkisch@web.de>
220

321
src/fit.c demo/fit.dem docs/gnuplot.doc: New syntax to specify errors.

‎NEWS‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
New features, changes and fixes since gnuplot version 4.6
22
=========================================================
33

4+
* NEW function plugins, e.g. 'import f(x) from "plugins.so"'
45
* NEW option to tabulate all input columns "set table; plot ... with table"
56
* NEW smoothing option "mcsplines" for piecewise monotonic cubic splines
67
* NEW 'history !N' reexecutes the command at history entry N.

‎config/config.nt‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@
9494
/* Define to 1 if you have the <errno.h> header file. */
9595
#define HAVE_ERRNO_H 1
9696

97+
/* Define if external function plugins are to be supported. */
98+
#define HAVE_EXTERNAL_FUNCTIONS 1
99+
97100
/* Define to 1 if you have the <float.h> header file. */
98101
#define HAVE_FLOAT_H 1
99102

‎configure.in‎

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
dnl Process this file with autoconf to produce a configure script.
22
dnl configure.in for gnuplot on Unix.
33
dnl
4-
dnl $Id: configure.in,v 1.350 2014/02/19 01:14:38 sfeam Exp $
4+
dnl $Id: configure.in,v 1.351 2014/02/24 22:12:38 sfeam Exp $
55
dnl
66
dnl this is actually major.minor ...
77
dnl note that for a non-beta release, we need to disable DEVELOPMENT_RELEASE
@@ -198,7 +198,8 @@ AC_CHECK_HEADERS(dirent.h errno.h float.h langinfo.h limits.h locale.h math.h \
198198
stdlib.h string.h time.h sys/time.h sys/types.h \
199199
sys/bsdtypes.h sys/ioctl.h sys/param.h sys/select.h sys/socket.h \
200200
sys/stat.h sys/systeminfo.h sys/timeb.h sys/utsname.h \
201-
libc.h malloc.h poll.h sgtty.h termios.h values.h dirent.h
201+
libc.h malloc.h poll.h sgtty.h termios.h values.h dirent.h \
202+
dlfcn.h dl.h
202203
)
203204

204205
AC_HEADER_STDBOOL
@@ -217,6 +218,26 @@ if test "$ac_cv_header_sys_stat_h" = yes; then
217218
AC_HEADER_STAT
218219
fi
219220

221+
dnl Check for external functions plugin infrastructure
222+
AC_ARG_ENABLE(plugins,dnl
223+
[ --disable-plugins disable support for importing external functions],,)
224+
225+
if test "$enable_plugins" != no; then
226+
if test "$ac_cv_header_dl_h" = yes; then
227+
AC_SEARCH_LIBS(shl_load, dld,
228+
[AC_DEFINE(HAVE_EXTERNAL_FUNCTIONS,1,[ Define if external function plugins are to be supported. ])
229+
have_external_functions=yes
230+
])
231+
fi
232+
if test "$ac_cv_header_dlfcn_h" = yes; then
233+
AC_SEARCH_LIBS(dlopen, dl,
234+
[AC_DEFINE(HAVE_EXTERNAL_FUNCTIONS,1,[ Define if external function plugins are to be supported. ])
235+
have_external_functions=yes
236+
])
237+
fi
238+
fi
239+
AM_CONDITIONAL(BUILD_PLUGIN, test "$have_external_functions" = yes)
240+
220241
dnl check if unistd actually declares anything. On NeXT 3.2 unistd is
221242
dnl conditionalized for _POSIX_SOURCE
222243
AC_MSG_CHECKING(for unistd.h)
@@ -1568,6 +1589,12 @@ else
15681589
AC_MSG_RESULT([ cerf() and other special functions: no (libcerf not found)])
15691590
fi
15701591

1592+
if test "$have_external_functions" = yes; then
1593+
AC_MSG_RESULT([ plugin support for loading external functions: yes (EXPERIMENTAL)])
1594+
else
1595+
AC_MSG_RESULT([ plugin support for loading external functions: no (EXPERIMENTAL)])
1596+
fi
1597+
15711598
if test "$with_kpsexpand" = yes; then
15721599
AC_MSG_RESULT([ Use TeX kpsexpand to search for fonts: yes])
15731600
else

‎demo/Makefile.am.in‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,14 @@ Makefile.am: Makefile.am.in
7474
sed -n '1,/^##m4-files-begin/p' Makefile.am.in > $@t
7575
echo EXTRA_DIST = Makefile.am.in *.bin *.cfg *.cor *.dat *.dem *.edf \
7676
*.fnc *.inc *.pdb *.png *.r3d *.rgb sound.par sound2.par \
77-
start.par *.rot gnu-valley random-points gpdemos.tcl html | fmt | \
77+
start.par *.rot gnu-valley random-points gpdemos.tcl html plugin | fmt | \
7878
(tr '\012' @; echo) | sed 's/@$$/%/;s/@/ \\@/g' | tr @% '\012 ' \
7979
>> $@t
80+
echo if BUILD_PLUGIN >> $@t
81+
echo SUBDIRS = plugin >> $@t
82+
echo else >> $@t
83+
echo SUBDIRS = >> $@t
84+
echo endif >> $@t
8085
sed -n '/^##m4-files-end/,$$p' $< >> $@t
8186
chmod og-w $@t
8287
mv $@t $@

‎demo/plugin/Makefile‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
PLUGIN=demo_plugin
2+
3+
all: $(PLUGIN).so
4+
5+
GNUPLOTSRC = ../..
6+
7+
CFLAGS = -DHAVE_CONFIG_H -I$(GNUPLOTSRC) -I$(GNUPLOTSRC)/src -rdynamic -fPIC
8+
9+
%.so: %.o
10+
$(CC) -shared $^ -o $@
11+
12+
clean:
13+
rm -f *.o *.so

‎demo/plugin/demo_plugin.c‎

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
The files demo_plugin.c and gnuplot_plugin.h serve as templates
3+
showing how to create an external shared object containing functions
4+
that can be accessed from inside a gnuplot session using the import
5+
command. For example, after compiling this file into a shared
6+
object (gnuplot_plugin.so or gnuplot_plugin.dll) the functions it
7+
contains can be imported as shown:
8+
9+
gnuplot> import divisors(x) from "demo_plugin"
10+
gnuplot> import mysinc(x) from "demo_plugin:sinc"
11+
gnuplot> import nsinc(N,x) from "demo_plugin"
12+
*/
13+
14+
#include "gnuplot_plugin.h"
15+
#include "math.h"
16+
17+
/* This funcstion returns the number of divisors of the first argument */
18+
19+
DLLEXPORT struct value divisors(int nargs, struct value *arg, void *p)
20+
{
21+
int a = IVAL(arg[0]);
22+
int i = 1;
23+
int j = a;
24+
struct value r;
25+
r.type = INTGR;
26+
r.v.int_val = 0;
27+
28+
/* Enforce a match between the number of parameters declared
29+
* by the gnuplot import command and the number implemented here.
30+
*/
31+
RETURN_ERROR_IF_WRONG_NARGS(r, nargs, 1);
32+
33+
/* Sanity check on argument type */
34+
RETURN_ERROR_IF_NONNUMERIC(r, arg[0]);
35+
36+
while (i <= j)
37+
{
38+
if (a == i*j)
39+
{
40+
r.v.int_val += 1 + (i!=j);
41+
}
42+
i++;
43+
j=a/i;
44+
}
45+
46+
return r;
47+
}
48+
49+
DLLEXPORT struct value sinc(int nargs, struct value *arg, void *p)
50+
{
51+
double x = RVAL(arg[0]);
52+
struct value r;
53+
r.type = CMPLX;
54+
55+
/* Enforce a match between the number of parameters declared
56+
* by the gnuplot import command and the number implemented here.
57+
*/
58+
RETURN_ERROR_IF_WRONG_NARGS(r, nargs, 1);
59+
60+
/* Sanity check on argument type */
61+
RETURN_ERROR_IF_NONNUMERIC(r, arg[0]);
62+
63+
r.v.cmplx_val.real = sin(x)/x;
64+
r.v.cmplx_val.imag = 0.0;
65+
66+
return r;
67+
}
68+
69+
DLLEXPORT struct value nsinc(int nargs, struct value *arg, void *p)
70+
{
71+
struct value r;
72+
int n; /* 1st parameter */
73+
double x; /* 2nd parameter */
74+
75+
/* Enforce a match between the number of parameters declared
76+
* by the gnuplot import command and the number implemented here.
77+
*/
78+
RETURN_ERROR_IF_WRONG_NARGS(r, nargs, 2);
79+
80+
/* Sanity check on argument type */
81+
RETURN_ERROR_IF_NONNUMERIC(r, arg[0]);
82+
RETURN_ERROR_IF_NONNUMERIC(r, arg[1]);
83+
84+
n = IVAL(arg[0]);
85+
x = RVAL(arg[1]);
86+
87+
r.type = CMPLX;
88+
r.v.cmplx_val.real = n * sin(x)/x;
89+
r.v.cmplx_val.imag = 0.0;
90+
91+
return r;
92+
}

‎demo/plugin/gnuplot_plugin.h‎

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
2+
#include <gp_types.h>
3+
4+
#ifdef WIN32
5+
# define DLLEXPORT __declspec(dllexport)
6+
# define __inline__ __inline
7+
#else
8+
# define DLLEXPORT
9+
#endif
10+
11+
/* prototype for a plugin function */
12+
DLLEXPORT void *gnuplot_init(struct value(*)(int, struct value *, void *));
13+
DLLEXPORT void gnuplot_fini(void *);
14+
15+
/* Check that the number of parameters declared in the gnuplot import
16+
* statement matches the actual number of parameters in the exported
17+
* function
18+
*/
19+
#define RETURN_ERROR_IF_WRONG_NARGS(r, nargs, ACTUAL_NARGS) \
20+
if (nargs != ACTUAL_NARGS) { \
21+
r.type = INVALID_VALUE; \
22+
return r; \
23+
}
24+
25+
#define RETURN_ERROR_IF_NONNUMERIC(r, arg) \
26+
if (arg.type != CMPLX && arg.type != INTGR) { \
27+
r.type = INVALID_VALUE; \
28+
return r; \
29+
}
30+
31+
__inline__ static double RVAL(struct value v)
32+
{
33+
if (v.type == CMPLX)
34+
return v.v.cmplx_val.real;
35+
else if (v.type == INTGR)
36+
return (double) v.v.int_val;
37+
else
38+
return 0; /* precluded by sanity check above */
39+
}
40+
41+
__inline__ static int IVAL(struct value v)
42+
{
43+
if (v.type == CMPLX)
44+
return (int)v.v.cmplx_val.real;
45+
else if (v.type == INTGR)
46+
return v.v.int_val;
47+
else
48+
return 0; /* precluded by sanity check above */
49+
}
50+
51+
#undef NaN

‎demo/plugin/plugin.dem‎

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#
2+
# demo for the use of external functions
3+
#
4+
if (!strstrt(GPVAL_COMPILE_OPTIONS,"+EXTERNAL_FUNCTIONS")) {
5+
print ">>> Skipping demo <<<\n" ;
6+
print "This copy of gnuplot does not support import of external functions"
7+
exit
8+
}
9+
10+
# This will look for an exported routined named divisors
11+
# in shared object example.so
12+
set title "import divisors from 'sharedobject'"
13+
import divisors(x) from "demo_plugin"
14+
set samples 10001, 10001
15+
plot [0:10000] divisors(x) w his
16+
17+
pause -1 "<cr> to continue"
18+
19+
# This will cause future invocations of g(x) to call the
20+
# routine sinc(x) contained in shared object example.so
21+
# I.e. g(x) is an alias for an external function sinc(x)
22+
set title "import g(x) from 'sharedobject:sinc'"
23+
import g(x) from "demo_plugin:sinc"
24+
plot [-20:20] g(x)
25+
26+
pause -1 "<cr> to continue"
27+
28+
# compare internal and external implementations of sinc(x)
29+
set title "Compare internal and external implementations of sinc"
30+
set samples 250
31+
sinc(x) = sin(x) / x
32+
plot sinc(x) - g(x)
33+
34+
pause -1 "<cr> to continue"
35+
36+
# Similar to above but using a 2-parameter function
37+
set title "Import a 2-parameter function"
38+
import nsinc(N,x) from "demo_plugin:nsinc"
39+
plot for [N=1:5] nsinc(N,x) lw 2 title sprintf("nsinc(%d,x)",N)
40+
41+
pause -1 "<cr> to continue"
42+
43+
reset

‎docs/gnuplot.doc‎

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
C RCS $Id: gnuplot.doc,v 1.853 2014/02/25 06:04:36 sfeam Exp $
1+
C RCS $Id: gnuplot.doc,v 1.854 2014/02/27 07:57:50 markisch Exp $
22
C
33
C Copyright (C) 1986 - 1993, 1998, 1999, 2000, 2001, 2004 Thomas Williams, Colin Kelley et al.
44
C
@@ -260,6 +260,11 @@ C
260260
math routines cerf, cdawson, erfi, faddeeva, and the Voigt profile
261261
VP(x,sigma,gamma).
262262

263+
* The `import` command attaches a user-defined function name to a function
264+
exported by an external shared object (support is operating-system dependent).
265+
A template header and example source and make files for creating a suitable
266+
external shared object are provided in the demo collection.
267+
263268
2 Deprecated syntax
264269
?deprecated syntax
265270
?backwards compatibility
@@ -4866,6 +4871,32 @@ Ffigure_mapcontours
48664871
set for [i=1:9] for [j=1:9] label i*10+j sprintf("%d",i*10+j) at i,j
48674872

48684873
See additional documentation for `iteration`, `do`.
4874+
2 import
4875+
?commands import
4876+
?import
4877+
The `import` command associates a user-defined function name with a function
4878+
exported by an external shared object. This constitutes a plugin mechanism
4879+
that extends the set of functions available in gnuplot.
4880+
4881+
Syntax:
4882+
import func(x[,y,z,...]) from "sharedobj[:symbol]"
4883+
4884+
Examples:
4885+
# make the function myfun, exported by "mylib.so" or "mylib.dll"
4886+
# available for plotting or numerical calculation in gnuplot
4887+
import myfun(x) from "mylib"
4888+
import myfun(x) from "mylib:myfun" # same as above
4889+
4890+
# make the function theirfun, defined in "theirlib.so" or "theirlib.dll"
4891+
# available under a different name
4892+
import myfun(x,y,z) from "theirlib:theirfun"
4893+
4894+
The program extends the name given for the shared object by either ".so" or
4895+
".dll" depending on the operating system, and searches for it first as a full
4896+
path name and then as a path relative to the current directory. The operating
4897+
system itself may also search any directories in LD_LIBRARY_PATH or
4898+
DYLD_LIBRARY_PATH.
4899+
48694900
2 load
48704901
?commands load
48714902
?load

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL