1

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

ikegami
  • 367,544
  • 15
  • 269
  • 518
Ami
  • 233
  • 2
  • 9
  • hmm? The documentation is quite clear. What did you try? – ikegami Apr 05 '22 at 06:09
  • @ikegami Not just documentation I checked Platypus.pm source code. As in old P5NCI.pm there were find_lib, load_lib,load_func subroutine defined. But in Platypus.pm I dont find all this subroutines, – Ami Apr 05 '22 at 06:17
  • *"This was working fine till perl-5.14, but later I used it for perl-5.26.3, but I am getting error"* : Yes I tested this on perl 5.34 and am getting the same error. The issue has been reported 10 years ago in [this](https://rt.cpan.org/Public/Bug/Display.html?id=77325) ticket – Håkon Hægland Apr 05 '22 at 10:46
  • *"ESNMP.so"* Can you provide a link to this library, or its source code? I tried to google it but could not find it – Håkon Hægland Apr 05 '22 at 10:51
  • @HåkonHægland: yes this is broken from perl 5.14 onwards, hence we are using alternate options like FFI:Platypus. ESNMP.so: this is my internal dynamic library generated from my C source code which I am loading and calling function inside id from perl code. – Ami Apr 05 '22 at 11:00
  • *"As in old P5NCI.pm there were find_lib, ... subroutine defined. But in Platypus.pm I dont find all this subroutine"* See https://metacpan.org/pod/FFI::CheckLib#find_lib . It should do the same as P5NCI::find_lib() – Håkon Hægland Apr 05 '22 at 11:22
  • @HåkonHægland, what about P5NCI::load_func or any suggestion for calling c function – Ami Apr 05 '22 at 11:33
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/243615/discussion-between-amit-m-and-hakon-haegland). – Ami Apr 05 '22 at 11:36
  • Re "*But in Platypus.pm I dont find all this subroutines,*", It's all in the SYNOPSYS! The first thing after the module's name and its version. Well, almost. You need to look down to `->lib` to load a library other than libc. – ikegami Apr 05 '22 at 13:21
  • If you have a new question, ask a new question – ikegami Apr 25 '22 at 14:38

2 Answers2

2

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.

Håkon Hægland
  • 39,012
  • 21
  • 81
  • 174
  • Great thanks a lot let me try this. – Ami Apr 05 '22 at 12:41
  • Hi @ Håkon Hægland, As I checked, if we provide, ESNMP name then for linux it checks for libESNMP.so while my legacy library name is ESNMP.so, is there any way to get exact library name . – Ami Apr 20 '22 at 12:22
  • 1
    As of now I proceeded with creating symbolic link: libESNMP.so -> ESNMP.so – Ami Apr 20 '22 at 12:31
  • @ Håkon Hægland Thanks for the solution this is working perfect. Thanks a lot. – Ami May 16 '22 at 13:21
1

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( ... );
ikegami
  • 367,544
  • 15
  • 269
  • 518
  • Thanks for your suggestion. After adding the changes I am facing new issues. I will create new question for that. – Ami Apr 25 '22 at 15:08