gants has asked for the wisdom of the Perl Monks concerning the following question:

hello, Could you tell me how that get to work? I tries make module from a book, but fails. it says
Undefined subroutine &Book::Factorial::factorial_iterative_c called at + fact.pl line 3.
factorial.h============================ double factorial_recursive_c(int x); double factorial_iterative_c(int +x); factorial.c============================ double factorial_recursive_c(int x) { if (x < 2) return 1; return x * factorial_recursive_c(x - 1); } double factorial_iterative_c(int x) { int i; double result = 1; for (i = 2; i <= x; i++) result *= i; return result; } ============================== $h2xs -n Book::Factorial -A -O -x -F factorial.h add 'OBJECT' => 'Factorial.o factorial.o', to Makefile.PL $perl Makefile.PL $make $make test $make install
everything installed well symbols in factorial.c existent...
23: 00000af0 45 FUNC GLOBAL DEFAULT 12 factorial_iterative +_c 26: 00000aa0 76 FUNC GLOBAL DEFAULT 12 factorial_recursive +_c testing script============================= use strict; use Book::Factorial; my $result = Book::Factorial::factorial_iterative_c(5); print $result;

Replies are listed 'Best First'.
Re: own perl module based on c library
by almut (Canon) on Apr 27, 2010 at 12:15 UTC

    Works for me...

    Here's the complete output of the build script that I used, so you can compare what's different in your case  (some whitespace added for clarity):

    $ ./build-factorial.sh ========== ./build-factorial.sh ========== #!/bin/sh for file in $0 factorial.h factorial.c 837069.pl ; do echo ========== $file ========== cat $file echo done echo ======================================== rm -rf ./Book-Factorial PERLBIN=/usr/local/perl/5.10.1/bin set -x # create extension $PERLBIN/h2xs -n Book::Factorial -Ax factorial.h cp factorial.[hc] Book-Factorial cd Book-Factorial # edit Makefile.PL perl -i -pe 's/# (OBJECT)/$1/' Makefile.PL # build $PERLBIN/perl Makefile.PL make test # check ../837069.pl ========== factorial.h ========== double factorial_recursive_c(int x); double factorial_iterative_c(int x); ========== factorial.c ========== double factorial_recursive_c(int x) { if (x < 2) return 1; return x * factorial_recursive_c(x - 1); } double factorial_iterative_c(int x) { int i; double result = 1; for (i = 2; i <= x; i++) result *= i; return result; } ========== 837069.pl ========== #!/usr/local/perl/5.10.1/bin/perl -l use strict; use warnings; use lib qw(./blib/lib ./blib/arch); # just to avoid the need for inst +allation use Book::Factorial; my $result = Book::Factorial::factorial_iterative_c(5); print $result; ======================================== + /usr/local/perl/5.10.1/bin/h2xs -n Book::Factorial -Ax factorial.h Defaulting to backwards compatibility with perl 5.10.1 If you intend this module to be compatible with earlier perl versions, + please specify a minimum perl version with the -b option. Writing Book-Factorial/ppport.h Scanning typemaps... Scanning /usr/local/perl/5.10.1/lib/5.10.1/ExtUtils/typemap Scanning factorial.h for functions... Scanning factorial.h for typedefs... Writing Book-Factorial/lib/Book/Factorial.pm Writing Book-Factorial/Factorial.xs Writing Book-Factorial/Makefile.PL Writing Book-Factorial/README Writing Book-Factorial/t/Book-Factorial.t Writing Book-Factorial/Changes Writing Book-Factorial/MANIFEST + cp factorial.c factorial.h Book-Factorial + cd Book-Factorial + perl -i -pe 's/# (OBJECT)/$1/' Makefile.PL + /usr/local/perl/5.10.1/bin/perl Makefile.PL Checking if your kit is complete... Looks good Writing Makefile for Book::Factorial + make test cp lib/Book/Factorial.pm blib/lib/Book/Factorial.pm /usr/local/perl/5.10.1/bin/perl /usr/local/perl/5.10.1/lib/5.10.1/ExtU +tils/xsubpp -typemap /usr/local/perl/5.10.1/lib/5.10.1/ExtUtils/type +map Factorial.xs > Factorial.xsc && mv Factorial.xsc Factorial.c Please specify prototyping behavior for Factorial.xs (see perlxs manua +l) /usr/local/bin/gcc -c -I. -fno-strict-aliasing -pipe -I/usr/local/in +clude -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -O2 -DVERSION=\"0. +01\" -DXS_VERSION=\"0.01\" -fPIC "-I/usr/local/perl/5.10.1/lib/5.10.1 +/x86_64-linux/CORE" Factorial.c /usr/local/bin/gcc -c -I. -fno-strict-aliasing -pipe -I/usr/local/in +clude -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -O2 -DVERSION=\"0. +01\" -DXS_VERSION=\"0.01\" -fPIC "-I/usr/local/perl/5.10.1/lib/5.10.1 +/x86_64-linux/CORE" factorial.c Running Mkbootstrap for Book::Factorial () chmod 644 Factorial.bs rm -f blib/arch/auto/Book/Factorial/Factorial.so /usr/local/bin/gcc -shared -O2 -L/usr/local/lib Factorial.o factoria +l.o -o blib/arch/auto/Book/Factorial/Factorial.so \ \ chmod 755 blib/arch/auto/Book/Factorial/Factorial.so cp Factorial.bs blib/arch/auto/Book/Factorial/Factorial.bs chmod 644 blib/arch/auto/Book/Factorial/Factorial.bs PERL_DL_NONLAZY=1 /usr/local/perl/5.10.1/bin/perl "-MExtUtils::Command +::MM" "-e" "test_harness(0, 'blib/lib', 'blib/arch')" t/*.t t/Book-Factorial.t .. ok All tests successful. Files=1, Tests=1, 0 wallclock secs ( 0.02 usr 0.00 sys + 0.02 cusr + 0.00 csys = 0.04 CPU) Result: PASS + ../837069.pl 120
Re: own perl module based on c library
by salva (Canon) on Apr 27, 2010 at 12:51 UTC
    have you copied factorial.c and factorial.h into the directory created by h2xs?

    It seems that h2xs is not able to generate the XS declarations for the functions in factorial.c

    That's what it produces in my machine:

    #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "ppport.h" MODULE = Book::Factorial PACKAGE = Book::Factorial

      Looks like the problem is the -F option to h2xs.  Not only is it useless here (which is why I dropped it), it's in fact the source of the problem, because it declares "factorial.h" to be a C preprocessor flag, so there remains no .h file to scan...

      $ h2xs -n Book::Factorial -A -O -x -F factorial.h Defaulting to backwards compatibility with perl 5.10.1 If you intend this module to be compatible with earlier perl versions, + please specify a minimum perl version with the -b option. Writing Book-Factorial/ppport.h Scanning typemaps... Scanning /usr/local/perl/5.10.1/lib/5.10.1/ExtUtils/typemap Writing Book-Factorial/lib/Book/Factorial.pm Writing Book-Factorial/Factorial.xs Writing Book-Factorial/Makefile.PL Writing Book-Factorial/README Writing Book-Factorial/t/Book-Factorial.t Writing Book-Factorial/Changes Writing Book-Factorial/MANIFEST ---- $ h2xs -n Book::Factorial -A -O -x factorial.h Defaulting to backwards compatibility with perl 5.10.1 If you intend this module to be compatible with earlier perl versions, + please specify a minimum perl version with the -b option. Writing Book-Factorial/ppport.h Scanning typemaps... Scanning /usr/local/perl/5.10.1/lib/5.10.1/ExtUtils/typemap Scanning factorial.h for functions... # <--- !! Scanning factorial.h for typedefs... Writing Book-Factorial/lib/Book/Factorial.pm Writing Book-Factorial/Factorial.xs Writing Book-Factorial/Makefile.PL Writing Book-Factorial/README Writing Book-Factorial/t/Book-Factorial.t Writing Book-Factorial/Changes Writing Book-Factorial/MANIFEST

      The latter variant produces the follwing correct Factorial.xs file:

      #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "ppport.h" #include <factorial.h> MODULE = Book::Factorial PACKAGE = Book::Factorial double factorial_iterative_c(x) int x double factorial_recursive_c(x) int x
        #include <stdio.h> int tst(int len,char str[1024]){ printf("called c from perl len:'%i' str:'%s' \n",len, str); return 1; } int main( ){ tst(54,"char"); return 1; }
        then what's wrong here, in C it works well, module for perl compiled well, but this
        use TST; TST::test(4444,"ss");
        prints called c from perl len:'4444'  str:'(null)'