如何用 FFI:Platypus 替换 cpan Perl 实用程序 P5NCI

How to replace cpan Perl utility P5NCI with FFI:Platypus

下面是调用 P5NCI::load_func 加载函数 load_library 的 perl 代码,其签名为 int load_library(int dummy),因此第三个参数作为 ii 传递给 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');

这在 perl-5.14 之前工作正常,但后来我将它用于 perl-5.26.3,但出现如下错误:

Don't understand NCI signature 'ii'

我正在考虑使用 FFI 鸭嘴兽。我已经使用以下步骤成功编译了 Platypus:

perl -MCPAN -e shell
install FFI::Platypus

想知道如何使用 FFI::Platypus 来实现与上述代码中使用 P5NCI

相同的目的

此致, 阿米特·门赫

相当于

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 );

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 );

这是从 module's documentation 的概要中几乎逐字复制的。以后请尝试回答您自己的问题。

请注意,我发现名为 load_library 的函数具有 int 参数非常可疑。它的参数真的是一个int吗?字符串似乎更有可能。但是,它在 P5NCI 版本中被声明为 int,所以我在 FFI::Platypus 版本中将其声明为 int


请注意,FFI 将查找 libESNMP.so,但您似乎有一个 unconventionally-named 库。您可以使用 P5NCI 用于查找它的相同函数,而不是使用 find_lib_or_die.

use Dynaloader qw( );

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

这是一个示例,说明如何使用 FFI::Platypus and FFI::CheckLib 来执行与 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;

注意,这里假定当前目录下有一个名为lib/libESNMP.so的文件(共享库)。这是我用来测试这个脚本的路径。我还假设在共享库中定义了一个名为 load_library() 的函数,它接受一个整数输入参数和 returns 一个整数。