我正在尝试使用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,所以我可能会遗漏一些东西。
答案 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