How to replace cpan Perl utility P5NCI with FFI:Platypus

148 views Asked by At

Below is perl code which calls P5NCI::load_func to load function load_library having signature as int load_library(int dummy), hence third argument is passed as ii to P5NCI::load_func

    my $library_path = P5NCI::find_lib( 'ESNMP.so' );
    $library      = P5NCI::load_lib( $library_path );
    print "\nLibrary loaded";
    print "\nlibrary_path".$library_path;
    my $funcldlib = P5NCI::load_func( $library, 'load_library', 'ii');

This was working fine till perl-5.14, but later I used it for perl-5.26.3, but I am getting error as below:

Don't understand NCI signature 'ii'

I am thinking to use FFI platypus. I have successfully compiled Platypus using below steps:

perl -MCPAN -e shell
install FFI::Platypus

Wanted to know how can I use FFI::Platypus to achieve same purpose as mentioned in above code with P5NCI

Regards, Amit Mendhe

2

There are 2 answers

4
Håkon Hægland On BEST ANSWER

Here is an example of how you can use FFI::Platypus and FFI::CheckLib to do the same as you did with P5NCI:

use feature qw(say);
use strict;
use warnings;
use FFI::Platypus;
use FFI::CheckLib;

my $libname = 'ESNMP';
my @libs = find_lib(lib => $libname, libpath => './lib');
die "Could not find libary '$libname'\n" if !@libs;
my $libpath = $libs[0];
my $ffi = FFI::Platypus->new();
$ffi->lib( $libpath );
my $function = $ffi->function('load_library', ['int'] => 'int');
my $input_value = 2;
my $return_value = $function->($input_value);
say "Return value: ", $return_value;

Note that this assumes that there is a file (the shared library) under the current directory called lib/libESNMP.so. This was the path I used for testing this script. I also assume that there is a function called load_library() defined in the shared library that takes an integer input argument and returns an integer.

1
ikegami On

The equivalent of

my $library_path = P5NCI::find_lib( 'ESNMP.so' );
my $library      = P5NCI::load_lib( $library_path );
my $funcldlib    = P5NCI::load_func( $library, 'load_library', 'ii' );

my $j = $funcldlib->( $i );

is

use FFI::Platypus qw( find_lib_or_die );
 
my $ffi = FFI::Platypus->new( api => 1 );
$ffi->lib( find_lib_or_die( lib => 'ESNMP' ) );
$ffi->attach( load_library => [ 'int' ] => 'int' );

my $j = load_library( $i );

This is copied almost verbatim from the module's documentation's synopsis. Please make an attempt to answer your own questions in the future.

Note that I find it very suspicious that a function called load_library has an int parameter. Is its parameter really an int? A string seems more likely. But, it was declared as an int in the P5NCI versions, so I declared it as an int in the FFI::Platypus version.


Note that FFI will look for libESNMP.so, but you appear to have an unconventionally-named library. You could use the very same function P5NCI used to find it instead of using find_lib_or_die.

use Dynaloader qw( );

my $lib_path = DynaLoader::dl_findfile( 'ESNMP' )
   or die( ... );