如何从Perl XS模块调用不同C源文件中的函数?

8
我正在使用Perl构建一个XS扩展,有两个文件:
  1. 一个C头文件(.h
  2. 一个C源文件(.c
目前我所做的是将所有C文件代码放在XS文件的Model=之前,并在Model=之后包装我想要的函数。
编译没有问题,我能够从perl中调用特定的函数。
但是我想将.xs文件与C文件分开。
我希望.xs文件只包含包装函数,这些函数将调用.c文件中的函数,但是当我这样做并运行dmake命令时,我得到错误代码129:对'parse.c'文件未定义的引用。
我试图使用C和OBJECT属性将.c文件包含在WriteMakerFile中,仍然出现错误。有什么办法可以将xs文件拆分为一个c文件和另一个xs文件,其中xs文件包装了.c文件的函数,并且这些函数是使用ExtUtils::MakeMaker的一部分。
如果有示例就更好了。
2个回答

10

这其实非常简单:

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 ..
测试通过 1 - 使用 My::Example;
测试通过 2 - hello 返回 "Hello"
1..2
测试通过
文件数=1,测试数=2,  0 壁钟秒 
( 0.04 用户  0.01 系统 +  0.03 c用户  0.00 c系统 =  0.08 CPU)
结果: 通过

Makefile.PL 是由 h2xs 生成的。我唯一改变的是取消以下行的注释:

# 如果你之后添加 C 文件需要链接,请取消注释这一行:
 OBJECT => '$(O_FILES)', # 链接所有 C 文件

1
我认为这是一个相当老的帖子,但我承认关键在于正确的目录结构和文件放置。您必须将其他.c源文件放入与xs文件相同的目录中。并将xs文件放入Makefile.PL所在的目录中。(假设您在Makefile.PL中没有将MULTIXS设置为1)。此放置限制的原因是生成的makefile中的CCCMD编译命令没有-o选项,因此所有输出对象文件都将放置在生成的Makefile所在的目录中。 在CPAN上,我发现/检查了一些模块,其源文件位于与xs文件不同的子目录中,但它们覆盖了ExtUtils :: MakeMaker const_cccmd子,并在Makefile生成期间动态添加了-o选项。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接