Perlããshared objectã®é¢æ°ãå¼ã³åºã
ä»åã®ãé¡
foo.so ã«å«ã¾ãã¦ããé¢æ° void func(void) ãPerlããå¼ã³åºãã
ãããã¿ã¤ã宣è¨ã®éããå¼æ°ã¯åããªããæ»ãå¤ããªãï¼ãããã¯è¦ãªãï¼ã
ããããã¯ããã¤ããã£ã¦ã
- æ®éãªãXSã¢ã¸ã¥ã¼ã«ãæ¸ãã¦å¯¾å¿ããã
- ãã ãã®ã·ã³ãã«ãªç®çã®ããã«XSã¢ã¸ã¥ã¼ã«ãæ¸ãã®ã¯ãããã大è¢è£ãããã
- ããå°ãç°¡åã«ãããã¨æã㨠Inline::C ãå©ç¨ããã
- ããã§ãå¥ã«æ§ããªãã£ãã®ã ãã©ãä»åã¯ãã®Perlã¹ã¯ãªãããã»ã¼åæã«ä¸¦åèµ·åããå¯è½æ§ããããã³ã³ãã¤ã«ãå¤éã«èµ°ãã®ãé¿ãããã
ã¨ãããã¨ã§ãã¡ãã£ã¨çããã¢ããã¼ãã¨ãã¦XSã¢ã¸ã¥ã¼ã«ã®ãã¼ã¹ã«ä½¿ããã¦ããDynaLoaderã¢ã¸ã¥ã¼ã«ãç´æ¥ä½¿ã£ã¦ã¿ããã¨ã«ããã
DynaLoaderã¨ã¯ï¼
Perlã§æããããã³ã¢ã¢ã¸ã¥ã¼ã«ã§ã*.soãã¡ã¤ã«ããã¼ããããã®ä¸ã®ã·ã³ãã«ãã¢ã¸ã¥ã¼ã«åå空éã«ãã¤ã³ãããå¦çããã¦ãããã
ä½è ã¯Tim Bunceã¨ãªã£ã¦ããããã¡ããä»ã«ãä½äººããé¢ãã£ã¦ããã¯ãã ãã©ã1994年製ãNYTProfãªã©ã®ä½è ã¨ãã¦æåã§ãä»ãPerlã§æ´»åãã¦ããã
ãã ãå©ç¨ã¤ã³ã¿ã¼ãã§ã¼ã¹ã¯ããªãå¤ããã®ã§ãããã¥ã¡ã³ããç´ æ°ãªãããããä¸ã«è»¢ãã£ã¦ãããµã³ãã«ãå°ãªããã¡ãã£ã¨ã¨ã£ã¤ãã«ãããããµã«ãªãæã£ã¦ããããªäººãæ¸ããã³ã¼ãã¯è»¢ãã£ã¦ããããä»åã®ãããªç¨éã«ã¯ãã¾ãå½¹ç«ã¡ããã«ãªãã£ãã
解決
perldocãè¦ãªããå®éã«æ¸ãã¦ã¿ããå®éã®ã¨ããã©ãããä½æ³ãæ£ããã®ãã¯ã£ããããªãã£ãããç¹ã«åé¡ãªãåããã®ã§ãããããããªæãã§ããã
ã¨ãã»ã³ã¹ã ããæãåºãã¨ä»¥ä¸ã®ããã«æ¸ãã
package ModCaller; use DynaLoader; our @ISA = qw(DynaLoader); my $libref = DynaLoader::dl_load_file("callee.so", 0x01); my $symref = DynaLoader::dl_find_symbol($libref, "show_message"); my $show_mes_ref = DynaLoader::dl_install_xsub("show_message", $symref, "callee.c");
- ã¾ã dl_load_file ã§shared objectã®ãã¡ã¤ã«ãèªã¿è¾¼ãã第2å¼æ°ã® 0x01 ã¯ãã®ä¾ã§ã¯ 0x00 ã§ããããä»ã® dl_load_file ã®ããã«å¿ è¦ã§ããã°ãªã³ã¯ãããããã®ãã©ã°ã
- 次㫠dl_symbol ã§ã©ã¤ãã©ãªä¸ã®ã·ã³ãã«ãæ¢ãã«è¡ããã·ã³ãã«ãè¦ä»ããããã°ãã®ãã¤ã³ã¿ãè¿ã£ã¦ããã
- Cãªããããå¼ã¹ã°ããããPerlã§ã¯ããããããªãã®ã§ãããåå空éã«ãã¤ã³ããããããã dl_install_xsub ã§ã第3å¼æ°(çç¥å¯è½)ã«ã¯ä¾å¤çºçæã«ã¡ãã»ã¼ã¸ã«åºããããã¡ã¤ã«åã渡ããã¨ãã§ããã
ãã®å¦çã«ãã£ã¦ ModCaller::show_message ãå®ç¾©ãããã
å®å ¨ãªãµã³ãã«ã³ã¼ã
ã¨ã©ã¼å¦çãå«ããå®å ¨ãªãµã³ãã«ã³ã¼ããä¸è¨ã«æ²è¼ããã
GitHubä¸ã«ãç½®ãã¦ããããhttps://github.com/limitusus/snippet/tree/master/perl-so
callee.c
callee.so ã«ã³ã³ãã¤ã«ãããCã³ã¼ã
#include <stdio.h> int show_message(void) { setbuf(stdout, 0); printf("this is a test message\n"); return 0; }
Makefile
callee.c ãã³ã³ãã¤ã«ã㦠callee.so ãçæããããã«æ¸ãã¦ãã
CFLAGS=-fPIC .PHONY: all clean all: callee.so callee.so: callee.o $(CC) -shared -fPIC -o $@ $^ callee.o: callee.c clean: $(RM) -f *.o callee.so *~
caller.pl
callee.so ã«å®ç¾©ããã¦ããé¢æ°ãå¼ã³åºãã ãã®ã·ã³ãã«ãªã³ã¼ã
#!/usr/bin/env perl use strict; use warnings; use 5.008; use ModCaller; ModCaller::show_message();
ModCaller.pm
ä»åã®ç®çãåå空éã« callee.so ã® show_message é¢æ°ãå°å ¥ã㦠Export ããã
package ModCaller; use strict; use warnings; use DynaLoader; use Exporter; our @ISA = qw(DynaLoader Exporter); our @EXPORT = (); our @EXPORT_OK = qw/show_message/; our $VERSION = "1.0"; my $libref = DynaLoader::dl_load_file("callee.so", 0x01); if (!$libref) { die "failed to load shared object"; } my $symref = DynaLoader::dl_find_symbol($libref, "show_message"); if (!$symref) { die "failed to find symbol"; } my $show_mes_ref = DynaLoader::dl_install_xsub("show_message", $symref, "callee.c"); if (!$show_mes_ref) { die "failed to install xsub"; } 1;
ãã£ã¨ããæ¸ãæ¹ãããã®ãããããªããã©ãç¿ä½ã¨ãããã¨ã§ã