Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 839
smith Avatar asked Apr 23 '14 12:04

smith


2 Answers

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
like image 161
Sinan Ünür Avatar answered Nov 09 '22 12:11

Sinan Ünür


I think this is a rather old post but I admit that the key is the proper directory structure and file placement. You must put the other .c source files into the same directory where your xs file is. And put your xs file into the directory where your Makefile.PL is. (I assume you do not set MULTIXS as 1 in your Makefile.PL). The reason for this placement restriction is that CCCMD compile command in generated makefile does not have -o option, so all output object files will be placed into the directory where your generated Makefile is. On CPAN I have found/checked some modules having source files in different sub dirs than xs file but they overrides ExtUtils::MakeMaker const_cccmd sub and append -o option on the fly during Makefile generation.

like image 1
DoubleB Avatar answered Nov 09 '22 12:11

DoubleB