在内联C库中调用函数

时间:2014-12-17 18:02:40

标签: c perl inline

我正在尝试使用CommonMark围绕Inline::C C库创建一个简单的包装器。我在libcmark.so安装了/usr/local/lib/

我目前的代码如下:

package Text::CommonMark;

use strict;
use warnings;

sub commonmarker {
    my $text = shift;
    return commonmark_to_html($text);
}

use Inline C => qq{

    char* commonmark_to_html(char* thetext) {

        char* result = cmark_markdown_to_html(thetext, strlen(thetext));
        return result;
    }
} => LIBS => '-L/usr/local/lib/ -llibcmark.so';

1;

当我从脚本中使用commonmarker时,我得到:

perl: symbol lookup error: /home/erik/sublimeworks/dists/Text-CommonMark/_Inline/lib/auto/Text/CommonMark_33fb/CommonMark_33fb.so: undefined symbol: cmark_markdown_to_html

我认为我对cmark_markdown_to_html的来电与其签名不符,但我found cmark_markdown_to_html的所有签名都是这样的:

char *cmark_markdown_to_html(const char *text, int len)

之前我没有接触过C或Inline :: C,所以我可能会遗漏一些东西。

2 个答案:

答案 0 :(得分:4)

文档中没有提及LIBS。该选项名为libs

use Inline C => config => libs => '-L/usr/local/lib/ -llibcmark.so';
use Inline C => <<'__EOC__';

    char* commonmark_to_html(char* thetext) {
        char* result = cmark_markdown_to_html(thetext, strlen(thetext));
        return result;
    }

__EOC__

请注意,使用char* thetext作为XS函数的参数是一个错误的确定标志。这为您提供了一个指向字符串缓冲区的指针,而不告诉您缓冲区的格式。

假设库接受并返回使用UTF-8编码的文本,

SV* commonmark_to_html(SV* text_sv) {
    STRLEN text_len;
    const char* text = SvPVutf8(text_sv, text_len);
    const char* html = cmark_markdown_to_html(text, text_len);
    SV* html_sv = newSVpvn_flags(html, strlen(html), SVf_UTF8);
    free(html);
    return html_sv;
}

稍微优化(因为使用newSVpvn_flags使标量变得更有效率使得使用类型映射生成的代码调用sv_2mortal):

void commonmark_to_html(SV* text_sv) {
    STRLEN text_len;
    const char* text = SvPVutf8(text_sv, text_len);
    const char* html = cmark_markdown_to_html(text, text_len);
    SV* html_sv = newSVpvn_flags(html, strlen(html), SVf_UTF8|SVs_TEMP);
    free(html);
    ST(0) = html_sv;
    XSRETURN(1);
}

答案 1 :(得分:2)

你的-l论证看起来很可疑。通常编译器/链接器将在&#34; lib&#34;之前加上前缀。并且后缀为&#34; .so&#34;,所以通常你应该只需要提供

-lcmark