perlperl-moduleperl-xs

How can I call functions in a different C source file from a Perl XS module?


I am building an XS extension with Perl. I have two files:

  1. A C header file (.h)
  2. A C source file (.c)

Currently what i did is to put all the C file code before the Model= on the XS file and wrap the functions I want after the Model=.

The compliation works with no problem and i am able to call the specific functions from perl.

But I want to separate the .xs file from the C file.

I want the .xs file to contain only the wrap functions, and those functions will call the functions on the .c file, but when I do that and run the dmake command i get error code 129 undefined reference to 'parse.c' file.

I tried to include the .c file using C and OBJECT properties for WriteMakerFile and still get an error any idea how to split the xs file to 2 one c file and the other xs which wrap the c function which are part of the .c file using ExtUtils::MakeMaker.

Examples would be appreciated.


Solution

  • This is actually rather straightforward:

    hello.h

    #ifndef H_HELLO
    const char *hello(void);
    #define H_HELLO
    #endif
    

    hello.c

    const char *
    hello(void) {
        return "Hello";
    }
    

    Example.xs

    #define PERL_NO_GET_CONTEXT
    #include "EXTERN.h"
    #include "perl.h"
    #include "XSUB.h"
    
    #include "ppport.h"
    
    #include "hello.h"
    
    MODULE = My::Example        PACKAGE = My::Example       PREFIX = MY_
    
    PROTOTYPES: DISABLE
    
    const char *
    MY_hello()
        CODE:
            RETVAL = hello();
        OUTPUT:
            RETVAL
    

    t/My-Example.t

    use strict;
    use warnings;
    
    use Test::More;
    BEGIN { use_ok('My::Example') };
    
    is(My::Example::hello(), 'Hello', 'hello returns "Hello"');
    
    done_testing;
    
    [~/tmp/My-Example]$ prove -vb t/My-Example.t
    t/My-Example.t ..
    ok 1 - use My::Example;
    ok 2 - hello returns "Hello"
    1..2
    ok
    All tests successful.
    Files=1, Tests=2,  0 wallclock secs 
    ( 0.04 usr  0.01 sys +  0.03 cusr  0.00 csys =  0.08 CPU)
    Result: PASS

    The Makefile.PL was generated by h2xs. The only thing I changed was to uncomment the following line:

    # Un-comment this if you add C files to link with later:
     OBJECT => '$(O_FILES)', # link all the C files too