NAME

ExtUtils::DynaLib - Perl extension for calling dynamically loaded C functions

SYNOPSIS

  use ExtUtils::DynaLib;
  $lib = new ExtUtils::DynaLib( $linker_arg );

  $func = $lib->declare_sub( $symbol_name
			     [, $return_type [, @arg_types] ] );
  $func = declare_sub( $function_pointer,
		       [, $return_type [, @arg_types] ] );
  $func = $lib->declare_sub( { "name"    => $symbol_name,
				["return" => $return_type,]
				["args"   => \@arg_types,]
				["decl"   => $decl,]
			      } );
  $func = declare_sub( { "ptr" => $function_pointer,
			 ["return" => $return_type,]
			 ["args"   => \@arg_types,]
			 ["decl"   => $decl,]
			 ["libref" => $libref,]
		       } );
  $result = $func->( @args );

  $callback = new ExtUtils::DynaLib::Callback( \&my_sub,
					       $return_type,
					       @arg_types );
  $callback_pointer = $callback->ptr();

DESCRIPTION

This module allows Perl programs to link with dynamic libraries and call their functions on the fly.

The mechanics of passing arguments and returning values are, unfortunately, highly machine-and-OS-dependent. Therefore, Makefile.PL checks the Perl configuration to verify that your architecture is supported.

Currently, this module has been built only on i586 Linux, FreeBSD, Sun4 Solaris and SunOS. It is expected to work on most Intel and many other platforms (at least with gcc), but the author won't change Makefile.PL to accept them until he has confirmation.

ExtUtils::DynaLib public constructor

The argument to new may be the file name of a shared library. Alternatively, a linker command-line argument (e.g., "-lc" for the C library) may be specified. See DynaLoader(3) for details on how such arguments are mapped to file names.

Declaring a library routine

Before you can call a function in a shared library, you must specify its name, the return type, and the number and types of arguments it expects. This is handled by declare_sub.

ExtUtils::DynaLib::declare_sub can be used as either an object method or an ordinary sub. Furthermore, you can pass its arguments either in a list (what we call "positional arguments") or in a hash ("named arguments").

The simplest way is to use declare_sub as a method using positional arguments. This form is illustrated in the first example above and both examples below. When used in this way, the first argument is a library function name, the second is the function return type, and the rest are function argument types.

The arguments to declare_sub are as follows:

name

The name of a function exported by $lib. This argument is ignored in the non-method forms of declare_sub.

ptr

The address of the C function. This argument is required in the non-method forms of declare_sub. Either it or the name must be specified in the method forms.

return

The return type of the function, encoded for use with the pack operator. Currently supported values are "" (void), "i" (int), "d" (double), "p" (a NUL-terminated character string), and "ptr" (any pointer type, usually equivalent to "i"; this is not a pack code because there isn't one for generic pointers that aren't dereferenced).

args

A list of the types of arguments expected by the function, specified using the notation of Perl's pack operator (see perlfunc(1)). For example, "i" means an integer, "d" means a double, "p" means a NUL-terminated string pointer.

Note: you probably don't want to use "c" or "s" here, since C normally converts the corresponding types (char and short) to int when passing them to a function. This module does not perform such conversions. Use "i" instead. Likewise, use "I" in place of "C" or "S".

decl

Allows you to specify a function's calling convention. This is possible only with a named-argument form of declare_sub. See below for information about the supported calling conventions.

libref

A library reference obtained from either DynaLoader::dl_load_file or the ExtUtils::DynaLib::libref method. You must use a named-argument form of declare_sub to specify this argument.

Calling a declared function

The return value of declare_sub is a code reference. Calling through it results in a call to the C function. See perlref(1) for how to call subs using code references.

Using callback routines

Some C functions expect a pointer to another C function as an argument. The library code that receives the pointer may use it to call an application function at a later time. Such functions are called callbacks.

This module allows you to use a perl sub as a C callback, subject to certain restrictions. There is a hard-coded maximum number of callbacks that can be active at any given time. The default (4) may be changed by specifying `CALLBACKS=number' as an argument to Makefile.PL.

A callback's argument and return types are specified using pack codes, as described above for library functions. Currently, the return value and first argument must be interpretable as type int or void, so the only valid codes are "i" and "". (On machines for which integers are the same size as pointers, "p" is allowed, too.) For argument positions beyond the first, the permissible types are "i", "p", and "d".

To enable a Perl sub to be used as a callback, you must construct an object of class ExtUtils::DynaLib::Callback. The syntax is

$cb_ref = new ExtUtils::DynaLib::Callback( \&some_sub,
                  $ret_type, @arg_types );

where $ret_type and @arg_types are the pack-style types of the function return value and arguments, respectively. The callback pointer is then obtained by calling $cb_ref->ptr().

EXAMPLES

This code loads and calls the math library function "sinh". It assumes that you have a dynamic version of the math library which will be found by DynaLoader::dl_findfile("-lm"). If this is not the case, replace "-lm" with the name of your math library.

use ExtUtils::DynaLib;
$libm = new ExtUtils::DynaLib("-lm");
$sinh = $libm->declare_sub("sinh", "d", "d");
print "The hyperbolic sine of 3 is ", &{$sinh}(3), "\n";
# The hyperbolic sine of 3 is 10.0178749274099

The following example uses the C library's "strncmp" to compare the first n characters of two strings:

use ExtUtils::DynaLib;
$libc = new ExtUtils::DynaLib("-lc");
$strncmp = $libc->declare_sub("strncmp", "i", "p", "p", "i");
$string1 = "foobar";
$string2 = "foolish";
$result = &{$strncmp}($string1, $string2, 3);  # $result is 0
$result = &{$strncmp}($string1, $string2, 4);  # $result is -1

The file test.pl contains examples of using a callback.

CALLING CONVENTIONS

ExtUtils::DynaLib currently supports the argument-passing conventions shown below. The module can be compiled with support for one or more of them by specifying (for example) `DECL=cdecl' on Makefile.PL's command-line. If none are given, Makefile.PL will try to choose based on your Perl configuration and give up if it can't guess.

At run time, a calling convention may be specified using a named-argument form of declare_sub (described above), or a default may be used. The first `DECL=...' will be the default.

Note that the convention must match that of the function in the dynamic library, otherwise crashes are likely to occur.

cdecl

All arguments are placed on the stack in reverse order from how the function is invoked. This seems to be the default for Intel-based machines and possibly others.

sparc

The first 24 bytes of arguments are cast to an array of six ints. The remaining args (and possibly piece of an arg) are placed on the stack. Then the C function is called as if it expected six integer arguments. On a Sparc, the six "pseudo-arguments" are passed in special registers.

hack30

This is not really a calling convention, it's just some C code that will successfully call a function most of the time on most systems tested so far. It is not especially efficient or elegant. There is a limit of 30 int-size arguments per function call (whence the name). Passing non-int-size arguments may be risky. Use it as a last resort.

BUGS

Several unresolved issues surround this module.

Portability

The "glue" code that allows Perl values to be passed as arguments to C functions is architecture-dependent. This is because the author knows of no standard means of determining a system's parameter-passing conventions or passing arguments to a C function whose signature is not known at compile time.

Because of this problem, we've tried to separate out the code associated with a particular calling format. We hope that support for more formats will be added in this way. However, we expect this to remain a tricky problem.

Robustness

Usually, Perl programs run under the control of the Perl interpreter. Perl is extremely stable and can almost guarantee an environment free of the problems of C, such as bad pointers causing memory access violations. Some Perl modules use a Perl feature called "XSubs" to call C code directly from a Perl program. In such cases, a crash may occur if the C or XS code is faulty. However, once the XS module has been sufficiently debugged, one can be reasonably sure that it will work right.

C code called through this module is devoid of such protection. Since the association between Perl and C is made at run time, errors due to incompatible library interfaces or incorrect assumptions have a much greater chance of causing a crash than with either static or XS code.

Security

This section is incomplete. I don't know what the security implications of this module may be. Use at your own risk.

Deallocation of Resources

To maximize portability, this module uses the DynaLoader(3) interface to shared library linking. DynaLoader's main purpose is to support XS modules, which are loaded once by a program and not (to the author's knowledge) unloaded. It would be nice to be able to free the libraries loaded by this module when they are no longer needed. This is impossible, since DynaLoader currently provides no means to do so.

Literal and temporary strings

Under Perl 5.004, it is impossible to pass a string literal as a pointer-to-nul-terminated-string argument of a C function. For example, the following statement (incorrectly) produces the error "Modification of a read-only value attempted":

$strncmp->("foo", "bar", 3);

To work around this problem, one must assign the value to a variable and pass the variable in its place, as in

$strncmp->($dummy1 = "foo", $dummy2 = "bar", 3);

This is related to the fact that Perl can not handle pack("p", "foo"). See the file "test.pl" for a patch to correct this behavior in the Perl source; I'm too lazy to work around it in this package.

Callbacks

The Callback code is non-reentrant (not thread-safe). And it assumes that pointers are packable as "I". Callbacks can mess up the message printed by die in the presence of nested evals.

Miscellaneous

There are too many restrictions on what C data types may be used. The techniques used to pass values to and from C functions are all very hackish and not officially sanctioned.

COPYING

This package is distributed under the same license as Perl itself. There is ABSOLUTELY NO WARRANTY. See the file "README" in the top level Perl source directory for details.

AUTHOR

John Tobey, jtobey@user1.channel1.com

SEE ALSO

perlfunc(1) (for pack), perlref(1), DynaLoader(3), perlxs(1), perlcall(1).