我需要将 perl EV::Loop 模块 (EV::default_loop) 中包含的循环对象传递到我的 C 库。
我有一个用 C 编写的测试库,它有一个函数 test,它将 struct ev_loop* 对象作为输入(EV_DEFAULT)。
ev_lib/EvManager.h:
#pragma once
#include<stdio.h>
#include <ev.h>
void test (struct ev_loop* loop);
static void time_cb (EV_P_ ev_timer *w, int revents);
static ev_timer timeout_watcher;
ev_lib/EvManager.c:
#include "EvManager.h"
void test (struct ev_loop* loop)
{
printf("%s\n", __PRETTY_FUNCTION__);
ev_verify(loop);
printf("%s\n", "check_loop(): ev_verify OK!");
ev_timer_init (&timeout_watcher, time_cb, 2, 2);
ev_timer_start (loop, &timeout_watcher);
return;
};
static void time_cb (EV_P_ ev_timer *w, int revents)
{
printf("EvManager.c: time_cb");
};
编译:
gcc -c -Wall -fpic EvManager.c
gcc -shared -o libevmanager.so EvManager.o -lev
我编写了使用 EVAPI.h 访问 C 循环对象的 .xs 模块(https://metacpan.org/pod/EV::MakeMaker):
EvTest.xs:
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "EVAPI.h"
#include "./ev_lib/EvManager.h"
static ev_timer timeout_watcher;
static void time_cb (EV_P_ ev_timer *w, int revents)
{
puts ("ev_timer_start (EvTest.xs): is called roughly every 2s (repeat = 2)");
};
static HV *stash;
MODULE = My::EvTest PACKAGE = My::EvTest
PROTOTYPES: ENABLE
BOOT:
{
stash = gv_stashpv ("My::EvTest" , 1);
I_EV_API ("My::EvTest");
}
void pass_loop_to_lib()
CODE:
{
ev_verify(EV_DEFAULT);
printf("%s\n", "pass_loop_to_lib(): ev_verify OK!");
ev_timer_init (&timeout_watcher, time_cb, 2, 2);
ev_timer_start (EV_DEFAULT, &timeout_watcher);
ev_verify(EV_DEFAULT);
printf("%s\n", "pass_loop_to_lib(): ev_verify (2) OK!");
test(EV_DEFAULT); // call ev_lib::test()
}
lib/My/EvTest.pm:
package My::EvTest;
use strict;
use warnings;
use Exporter qw(import);
our %EXPORT_TAGS = ( 'all' => [ qw( ) ] );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw( );
our $VERSION = 0.01;
require XSLoader;
XSLoader::load();
1;
Makefile.PL:
use 5.020;
use strict;
use warnings;
use utf8;
use ExtUtils::MakeMaker 6.98; # for XSMULTI option
use EV::MakeMaker qw(ev_args);
WriteMakefile(ev_args(
NAME => 'My::EvTest',
VERSION_FROM => 'lib/My/EvTest.pm',
PREREQ_PM => { 'ExtUtils::MakeMaker' => '6.98' },
ABSTRACT_FROM => 'lib/My/EvTest.pm',
OPTIMIZE => '-O2',
LICENSE => 'perl',
LIBS => ["-L./ev_lib -levmanager", "-lev"],
INC => '-I. -I/usr/include -I./ev_lib/'));
编译:
perl Makefile.PL
make -f Makefile
我的 perl 脚本使用模块 My::EvTest:
#!/usr/bin/perl -w
use FindBin 1.51 qw( $RealBin );
use strict;
use warnings;
use Devel::Peek;
use ExtUtils::testlib;
use EV;
use My::EvTest;
my $w = EV::timer 3, 3, sub
{
warn "EV::timer (.pm): is called roughly every 3s (repeat = 3)";
};
my $loop = EV::default_loop;
Dump $loop;
My::EvTest::pass_loop_to_lib();
EV::run;
exit(0);
我有这个输出:
➜ ./test_ev
SV = IV(0x9a8d30) at 0x9a8d40
REFCNT = 1
FLAGS = (PADMY,ROK)
RV = 0x9c6738
SV = PVMG(0x99eb60) at 0x9c6738
REFCNT = 3
FLAGS = (OBJECT,IOK,pIOK)
IV = 139812219366784
NV = 0
PV = 0
STASH = 0xa03ad0 "EV::Loop"
pass_loop_to_lib(): ev_verify OK!
pass_loop_to_lib(): ev_verify (2) OK!
test
perl: ev.c:2848: ev_verify: Проверочное утверждение «((loop)->anfdmax) >= 0» не выполнено.
Аварийный останов
我做错了什么?