如何将 perl EV::Loop 对象传递给您的 C 库

问题描述 投票:0回答:0

我需要将 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: Assertion «((loop)->anfdmax) >= 0» failed.
Aborted

我做错了什么?

c perl lib
© www.soinside.com 2019 - 2024. All rights reserved.