File: dlmodule.html

package info (click to toggle)
xmgr 4.1.2-2
  • links: PTS
  • area: main
  • in suites: slink
  • size: 5,544 kB
  • ctags: 6,680
  • sloc: ansic: 79,050; sh: 1,812; makefile: 278; perl: 90; fortran: 66
file content (205 lines) | stat: -rw-r--r-- 6,873 bytes parent folder | download | duplicates (5)
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
<HTML>

<HEAD>
<TITLE>ACE/gr: Dynamic loading of external modules</TITLE>
</HEAD>

<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#FF0000" VLINK="#FF0000" ALINK="#FF0000">

<H2>Dynamic loading of user defined modules</H2>
Since version 4.1.1, ACE/gr can access external functions present in either
system or third-party shared libraries or modules specially compiled for use 
with ACE/gr.
<H3> <A NAME="types">Function types</A></H3>
One must make sure, however, that the external function is of one of supported
by ACE/gr types:
<P>
<TABLE BORDER="3" BGCOLOR="#DDDDDD">
  <TR> <TH ALIGN="left">f_of_i</TH>    <TD>a function of 1 <CODE>int</CODE> variable</TD>                                         </TR>
  <TR> <TH ALIGN="left">f_of_d</TH>    <TD>a function of 1 <CODE>double</CODE> variable</TD> 		                          </TR>
  <TR> <TH ALIGN="left">f_of_nn</TH>   <TD>a function of 2 <CODE>int</CODE> parameters</TD>  		                          </TR>
  <TR> <TH ALIGN="left">f_of_nd</TH>   <TD>a function of 1 <CODE>int</CODE> parameter and 1 <CODE>double</CODE> variable</TD>     </TR>
  <TR> <TH ALIGN="left">f_of_dd</TH>   <TD>a function of 2 <CODE>double</CODE> variables</TD>			                  </TR>
  <TR> <TH ALIGN="left">f_of_nnd</TH>  <TD>a function of 2 <CODE>int</CODE> parameters and 1 <CODE>double</CODE> variable</TD>    </TR>
  <TR> <TH ALIGN="left">f_of_ppd</TH>  <TD>a function of 2 <CODE>double</CODE> parameters and 1 <CODE>double</CODE> variable</TD> </TR>
  <TR> <TH ALIGN="left">f_of_pppd</TH> <TD>a function of 3 <CODE>double</CODE> parameters and 1 <CODE>double</CODE> variable</TD> </TR>
</TABLE>			       
<P>
The return values of functions are assumed to be of the <CODE>double</CODE>
type.
<P>
Note, that there is no difference from the point of view of function prototype
between parameters and variables; the difference is in the way ACE/gr treats
them - an attempt to use a vector expression as an parameter argument will result
in a parse error.
<P>
Let us consider few examples.

<H3>Examples</H3>

Caution: the examples provided below (paths and compiler flags) are valid for
Linux/ELF with gcc. On other operating systems, you may need to refer to
compiler/linker manuals or ask a guru.

<H4>Example 1</H4>

Suppose I want to use function <CODE>pow(x,y)</CODE> from the Un*x math library
(libm). Of course, you can use the "<B>^</B>" operator defined in the ACE/gr
language, but here, for the sake of example, we want to access the function
directly.
<BR>
The command to make it accessible by ACE/gr is <BR>
<DL>
<DD> USE "pow" TYPE f_of_dd FROM "/usr/lib/libm.so"
</DL>
Try to plot y = pow(x,2) and y = x^2 graphs (using, for example, 
"Data-&gt;Edit/Create set-&gt;Formula") and compare :)

<H4>Example 2</H4>

Now, let us try to write a function ourselves. We will define function 
<CODE>my_function</CODE> which simply returns its (second) argument multiplied
by integer parameter transferred as the first argument.
<P>
In a text editor, type in the following C code and save it as "my_func.c":
<BR>
<TABLE BGCOLOR="#D8D8BF" WIDTH="100%">
<TR BGCOLOR="#DDDDDD"><TH>my_func.c</TH></TR>
<TR><TD>
<PRE>
double my_function (int n, double x)
{
    double retval;
    retval = (double) n * x;
    return (retval);
}
</PRE>
</TD></TR>
</TABLE>
OK, now compile it:
<BR>
<PRE>
$gcc -c -fPIC my_func.c
$gcc -shared my_func.o -o /tmp/my_func.so
</PRE>
(You may strip it to save some disk space):
<BR>
<PRE>
$strip /tmp/my_func.so
</PRE>
That's all! Ready to make it visible to ACE/gr as "myf" - we are too lazy
to type the very long string "my_function" many times :)
<BR>
<DL>
<DD> USE "my_function" TYPE f_of_nd FROM "/tmp/my_func.so" ALIAS "myf"
</DL>

<H4>Example 3</H4>
A more serious example. There is a special third-party library available on
your system which includes a very important for you yet very 
difficult-to-program from the scratch function that you want to use with ACE/gr.
But, the function prototype is NOT one of any predefined <A HREF="#types">types</A>.
The solution is to write a simple function wrapper. Here is how:
<BR>
Suppose, the name of the library is "special_lib" and the function you are
interested in is called "special_func" and according to the library manual,
should be accessed as 
<CODE>void special_func(double *input, double *output, int parameter)</CODE>.
The wrapper would look like this:
<BR>
<TABLE BGCOLOR="#D8D8BF" WIDTH="100%">
<TR BGCOLOR="#DDDDDD"><TH>my_wrapper.c</TH></TR>
<TR><TD>
<PRE>
double my_wrapper(int n, double x)
{
    extern void special_func(double *x, double *y, int n);
    double retval;
    (void) special_func(&amp;x, &amp;retval, n);
    return (retval);
}
</PRE>
</TD></TR>
</TABLE>
Compile it:
<BR>
<PRE>
$gcc -c -fPIC my_wrap.c
$gcc -shared my_wrap.o -o /tmp/my_wrap.so -lspecial_lib -lblas
$strip /tmp/my_wrap.so
</PRE>
Note that I added <CODE>-lblas</CODE> assuming that the special_lib library 
uses some functions from the BLAS. Generally, you have to add <i>all</i>
libraries which your module depends on (and all libraries those libraries
rely upon etc.), as if you wanted to compile a plain executable.
<BR>
Fine, make ACE/gr aware of the new function
<DL>
<DD> USE "my_wrapper" TYPE f_of_nd FROM "/tmp/my_wrap.so" ALIAS "special_func"
</DL>
so we can use it with its original name.

<H4>Example 4</H4>
An example of using Fortran modules.
<BR>
Here we will try to achieve the same functionality as in Example 2, but with the
help of F77.
<BR>
<TABLE BGCOLOR="#D8D8BF" WIDTH="100%">
<TR BGCOLOR="#DDDDDD"><TH>myfunc.f</TH></TR>
<TR><TD>
<PRE>
      DOUBLE PRECISION FUNCTION MYFUNC (N, X)
      IMPLICIT NONE
      INTEGER N
      DOUBLE PRECISION X
C
      MYFUNC = N * X
C
      RETURN
      END
</PRE>
</TD></TR>
</TABLE>
<P>
As opposite to C, there is no way to call such a function from ACE/gr directly -
the problem is that in Fortran all arguments to a function (or subroutine) are
passed by reference. So, we need a wrapper:
<BR>
<TABLE BGCOLOR="#D8D8BF" WIDTH="100%">
<TR BGCOLOR="#DDDDDD"><TH>myfunc_wrap.c</TH></TR>
<TR><TD>
<PRE>
double myfunc_wrapper(int n, double x)
{
    extern double myfunc_(int *, double *);
    double retval;
    retval = myfunc_(&amp;n, &amp;x);
    return (retval);
}
</PRE>
</TD></TR>
</TABLE>
<P>
Note that most of f77 compilers by default add underscore to the function names
and  convert all names to the lower case, hence I refer to the Fortran function
<CODE>MYFUNC</CODE> from my C wrapper as <CODE>myfunc_</CODE>, but in your case
it can be different!
<BR>
Let us compile the whole stuff:
<BR>
<PRE>
$g77 -c -fPIC myfunc.f
$gcc -c -fPIC myfunc_wrap.c
$gcc -shared myfunc.o myfunc_wrap.o -o /tmp/myfunc.so -lf2c -lm
$strip /tmp/myfunc.so
</PRE>
<P>
And finally, inform ACE/gr about this new function:
<DL>
<DD> USE "myfunc_wrapper" TYPE f_of_nd FROM "/tmp/myfunc.so" ALIAS "myfunc"
</DL>

</BODY>

</HTML>