warlock has asked for the wisdom of the Perl Monks concerning the following question:

I have written code using XS without problems. In all those programs I have written the C-code into the xs file. But now, I have tried to use a function defined in an other shared-object file, and although the building process does not print errors, when I use the pm-module (in "make test" for example) it returns "undefined symbol" error. During the shared-object building, make-process shows me the following message: "linker input file unused because linking not done". This warning explains the previous error. In C-code the symbols are resolved in executable files, not in shared-objects. But Perl import C-code as a shared-object, and so how can I resolve this problem??

-----------------------/tmp/prova2/helloworld/Makefile-----------------------
# Makefile MODULE=helloworld TYPEMAP=/usr/local/lib/perl5/5.8.7/ExtUtils/typemap XSUBPP=/usr/local/lib/perl5/5.8.7/ExtUtils/xsubpp PERLCORE=/usr/local/lib/perl5/5.8.7/i686-linux/CORE CC=gcc .PHONY: init clean all : init libhelloworld.so init : perl -e "use Devel::PPPort; use ExtUtils::Constant q +w (WriteConstants); \ Devel::PPPort::WriteFile(); WriteConstants(NAME => ' +$(MODULE)')" libhelloworld.so : helloworld.o $(CC) -shared helloworld.o -o $@ helloworld.c : helloworld.xs perl $(XSUBPP) -typemap $(TYPEMAP) helloworld.xs >$@ helloworld.o : helloworld.c $(CC) -Wall -fPIC -I$(PERLCORE) -I. -c helloworld.c +-Wl,-rpath,. -o $@ clean : rm -f helloworld.o helloworld.c const-c.inc const-xs +.inc ppport.h clean-all : clean rm -f libhelloworld.so
-----------------------/tmp/prova2/helloworld/helloworld.xs-----------------------
#include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "ppport.h" #include <helloworld.h> #include "const-c.inc" #include "extlibs/myprint.h" //#include "extlibs/myprint.c" MODULE = helloworld PACKAGE = helloworld INCLUDE: const-xs.inc void helloworld_proc() CODE: printf ("Helloworld\n"); boxing_print ("Helloworld");
-----------------------/tmp/prova2/helloworld/helloworld.pm-----------------------
package helloworld; use 5.008007; use strict; use warnings; use Carp; require XSLoader; our $VERSION = '0.01'; XSLoader::load('helloworld', $VERSION); 1;
-----------------------/tmp/prova2/helloworld/extlibs/Makefile---------------------
# Makefile localpath=/tmp/prova2/helloworld/extlibs LD_RUN_PATH=$(localpath) CC=gcc .PHONY: clean clean-all all : libmyprint.so test myprint.o : myprint.c $(CC) -c myprint.c -Fpic -o $@ libmyprint.so : myprint.o myprint.h $(CC) -shared myprint.o -o $@ test : test.c $(CC) -Wall test.c -I$(localpath) -L$(localpath) -Wl +,-rpath,$(localpath) -lmyprint -o $@ clean : rm -f *.o clean-all : clean rm -f *.so test
-----------------------/tmp/prova2/helloworld/extlibs/myprint.c----------------------
#include "stdio.h" #include "string.h" #include "myprint.h" void boxing_print (char *st) { int t=0; for (t=0; t<strlen(st); t++) printf ("-"); printf ("\n%s\n", st); for (t=0; t<strlen(st); t++) printf ("-"); printf ("\n"); return; }
-----------------------/tmp/prova2/helloworld/extlibs/myprint.h-----------------------
void boxing_print (char*);
Thank you for your help. Best regards Warlock

Replies are listed 'Best First'.
Re: shared-obj linking in xs-module
by rafl (Friar) on Mar 16, 2006 at 13:25 UTC

    I think the reason why this cannot work is, that you don't link the shared object, that contains your c symbols (libmyprint.so) into the XS shared object. You could either do that dynamically so that the symbols will be resolved at runtime, like you do with the test program for libmyprint.so, or you can just link it in there statically to make sure it will always work, even if someone moves libmyprint.so or even deletes it.

    That's my educated guess. It would help if you could post the build error, though.

    Cheers, Flo

      Thank you for your answer. But the problem is that "test" is an executable file, it is not a shared-obj. I cannot resolve myprints's symbols in libhelloworld.so. However I have tried to do this in helloworld.o:
      helloworld.o : helloworld.c $(CC) -Wall -fPIC -I$(PERLCORE) -I. -c helloworld.c +-Wl,-rpath,$(EXTLIB_PATH) -o $@ -L$(EXTLIB_PATH) -lmyprint
      without success. What do you suggest me?

        You're trying to link an object (.o) file against a library. You should do that with the shared-object file (.so).

        For example I use this commandline to link some of my XS code against a shared library.

        cc -shared -L/usr/local/lib xs/Connection.o xs/Loudmouth.o xs/Message +.o \ xs/MessageHandler.o xs/MessageNode.o xs/Proxy.o xs/SSL.o perlmouth.o \ build/perlmouth-gtypes.o -o blib/arch/auto/Net/Jabber/Loudmouth/Loudm +outh.so \ -lloudmouth-1 -lglib-2.0 -lgobject-2.0 -lgthread-2.0

        This works pretty well.

        Another possibility would be to link the libmyprint object file (.o) together with helloworld.o into helloworld.so.

        Cheers, Flo