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

Intro

I'm trying to create a PerlXS-Modul, that uses a C++ Class. Before diving into the complex matter, I wanted to create a little Test, to see how the basics work, since this is my first time using PerlXS. Luckily I tumbled upon this http://www.perlmonks.org/?node_id=853194 thread, which is a pretty awesome piece of knowledge. So I started to create my own litte Testclass, according to the example in the tutorial.

The Problem

While 'make' works without errors, but the include ( make test etc.) of the modul into a perl script fails with the following error:
Error: Can't load '/home/dr/Abby/XS/Mytest/blib/arch/auto/Mytest/Myte +st.so' for module Mytest: /home/dr/Abby/XS/Mytest/blib/arch/auto/Myte +st/Mytest.so: undefined symbol: _ZN7MyClassD1Ev at /usr/lib/perl/5.14 +/DynaLoader.pm line 184.
I tried to as close a possibly with the tutorial, but something is off, and I don't know what. Has anyone seen something similar? Any hints?

Code

I created the folder structure using h2xs -A -n Mytest In there I created a folder, called 'myclass', where the code for my C++ Class

C++ Part

myclass.h
#ifndef MyClass_H #define MyClass_H class MyClass { public: MyClass(int a, int b); ~MyClass(); int area(); private: int length; int width; }; #endif
myclass.cpp
#include "myclass.h" using namespace std; MyClass::MyClass (int length, int width) { this->length = length; this->width = width; } int MyClass::area() { return this->length*this->width; } </class> Makefile.PL This I basically took from the Tutorial mentioned in the Into, and adj +usted it to my changes. <code> use ExtUtils::MakeMaker; my ( $CC, $Verbose ) = ( 'g++', 1 ); WriteMakefile( NAME => 'Mytest::myclass', SKIP => [qw(all static static_lib dynamic dynamic_lib)], clean => {'FILES' => 'libmyclass$(LIB_EXT) unitTest'}, CC => $CC, # Our CPP compiler LD => '$(CC)', CCFLAGS => '-fPIC', # this instructs the CPP compiler to use "Posi +tion independence", basically a shared library, more details here # http://www.fpx.de/fp/Software/tcl-c++/tc ++l-c++.html ); sub MY::top_targets { ' all :: static pure_all :: static static :: libmyclass$(LIB_EXT) libmyclass$(LIB_EXT): $(O_FILES) $(AR) cr libmyclass$(LIB_EXT) $(O_FILES) $(RANLIB) libmyclass$(LIB_EXT) bin: $(O_FILES) $(LD) $(O_FILES) -o unitTest '; }
To test all these I wrote a litte unitTest, which worked fine. So I can safely assume, that my problem is not within the C++ part.

XS-Part and Makefile.PL

Mytest.xs
#include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "ppport.h" #include "myclass/myclass.h" MODULE = Mytest PACKAGE = Mytest MyClass* MyClass::new(int a, int b) int MyClass::area() void MyClass::DESTROY()
typemap  MyClass *      T_PTROBJ Makefile.PL
use 5.014002; use ExtUtils::MakeMaker; # See lib/ExtUtils/MakeMaker.pm for details of how to influence # the contents of the Makefile that is written. my $CC = 'g++'; WriteMakefile( NAME => 'Mytest', VERSION_FROM => 'lib/Mytest.pm', # finds $VERSION PREREQ_PM => {}, # e.g., Module::Name => 1.1 CC => $CC, # Our CPP compiler LD => '$(CC)', ($] >= 5.005 ? ## Add these new keywords supported since 5.005 (ABSTRACT_FROM => 'lib/Mytest.pm', # retrieve abstract from mod +ule AUTHOR => 'Dennis Rieber <dr@>') : ()), LIBS => [''], # e.g., '-lm' DEFINE => '', # e.g., '-DHAVE_SOMETHING' INC => '-I.', # e.g., '-I. -I/usr/include/other' # Un-comment this if you add C files to link with later: # OBJECT => '$(O_FILES)', # link all the C files too MYEXTLIB => 'myclass/libmyclass$(LIB_EXT)', # TYPEMAPS => ['perlobject.map' ], ); sub MY::postamble { ' $(MYEXTLIB): myclass/Makefile cd myclass && $(MAKE) $(PASSTHRU) '; }
t/Mytest.t
# Before `make install' is performed this script should be runnable wi +th # `make test'. After `make install' it should work as `perl Mytest.t' ######################### # change 'tests => 1' to 'tests => last_test_to_print'; use strict; use warnings; use Test::More tests => 2; BEGIN { use_ok('Mytest') }; my $class = new Mytest::MyClass(2,3); is($class->area(), 6, 'area_ok') ######################### # Insert your test code below, the Test::More module is use()ed here s +o read # its man page ( perldoc Test::More ) for help writing this test scrip +t.
MANIFEST
Changes Makefile.PL MANIFEST Mytest2.xs ppport.h README t/Mytest2.t lib/Mytest2.pm
This should be all the relevant code, or did I miss something?

Replies are listed 'Best First'.
Re: Unable to use created PerlXS Modul ( using c++ )
by Anonymous Monk on Feb 10, 2014 at 09:46 UTC

    Did libmyclass build successfully? What files did you get? Do any of these files (or their folder paths) get mentioned in Makefile? You should try adding those LIBS=-Ldirpath

    Also, all the myclass files should be in MANIFEST also

      libmyclass builds successfully, and the test I created for it works fine. I added the myclass/myclass.h/.cpp and the Makefile.PL to the manifest. Added '-L/home/dr/Abby/XS/Mytest/myclass' to LIBS. myclass/libmyclass gets mentions in the Makefile as MYEXTLIB. Nothing solved the problem so far. This is the output of the make-command:
      Skip blib/lib/Mytest.pm (unchanged) cd myclass && make make[1]: Betrete Verzeichnis '/home/dr/Abby/XS/Mytest/myclass' g++ -c -fPIC -O2 -g -DVERSION=\"\" -DXS_VERSION=\"\" -fPIC "-I/usr +/lib/perl/5.14/CORE" myclass.cpp ar cr libmyclass.a myclass.o unitTest.o : libmyclass.a make[1]: Verlasse Verzeichnis '/home/dr/Abby/XS/Mytest/myclass' make[1]: Betrete Verzeichnis '/home/dr/Abby/XS/Mytest/myclass' make[1]: Für das Ziel »all« ist nichts zu tun. make[1]: Verlasse Verzeichnis '/home/dr/Abby/XS/Mytest/myclass' g++ -c -I. -D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fno-strict-aliasing - +pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FI +LE_OFFSET_BITS=64 -O2 -g -DVERSION=\"0.01\" -DXS_VERSION=\"0.01\" - +fPIC "-I/usr/lib/perl/5.14/CORE" Mytest.c Running Mkbootstrap for Mytest () chmod 644 Mytest.bs rm -f blib/arch/auto/Mytest/Mytest.so g++ -shared -O2 -g -L/usr/local/lib -fstack-protector Mytest.o -o bl +ib/arch/auto/Mytest/Mytest.so myclass/libmyclass.a \ \ chmod 755 blib/arch/auto/Mytest/Mytest.so cp Mytest.bs blib/arch/auto/Mytest/Mytest.bs chmod 644 blib/arch/auto/Mytest/Mytest.bs Manifying blib/man3/Mytest.3pm
      and this for make test
      make[1]: Betrete Verzeichnis '/home/dr/Abby/XS/Mytest/myclass' make[1]: Für das Ziel »all« ist nichts zu tun. make[1]: Verlasse Verzeichnis '/home/dr/Abby/XS/Mytest/myclass' PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_h +arness(0, 'blib/lib', 'blib/arch')" t/*.t t/Mytest.t .. 1/2 # Failed test 'use Mytest;' # at t/Mytest.t line 12. # Tried to use 'Mytest'. # Error: Can't load '/home/dr/Abby/XS/Mytest/blib/arch/auto/Mytes +t/Mytest.so' for module Mytest: /home/dr/Abby/XS/Mytest/blib/arch/aut +o/Mytest/Mytest.so: undefined symbol: _ZN7MyClassD1Ev at /usr/lib/per +l/5.14/DynaLoader.pm line 184. # at (eval 4) line 2 # Compilation failed in require at (eval 4) line 2. # BEGIN failed--compilation aborted at (eval 4) line 2. Can't locate object method "new" via package "Mytest" at t/Mytest.t li +ne 14. # Looks like you planned 2 tests but ran 1. # Looks like you failed 1 test of 1 run. # Looks like your test exited with 255 just after 1. t/Mytest.t .. Dubious, test returned 255 (wstat 65280, 0xff00) Failed 2/2 subtests Test Summary Report ------------------- t/Mytest.t (Wstat: 65280 Tests: 1 Failed: 1) Failed test: 1 Non-zero exit status: 255 Parse errors: Bad plan. You planned 2 tests but ran 1. Files=1, Tests=1, 0 wallclock secs ( 0.03 usr 0.00 sys + 0.03 cusr + 0.00 csys = 0.06 CPU) Result: FAIL Failed 1/1 test programs. 1/1 subtests failed. make: *** [test_dynamic] Fehler 255
Re: Unable to use created PerlXS Modul ( using c++ )
by lamchob (Initiate) on Feb 11, 2014 at 09:57 UTC

    I've been tinkering a bit, and found the following baviour: When the Classfunctions of the c++ class are placed in the headerfile or the class is directly defined in the head of the .xs file like this:

    class foo { public: foo(int a) { value = a; } private: int value; }
    (like in http://www.johnkeiser.com/perl-xs-c%2B%2B.html another neat XS/C++ source), everything works as expected. The moment the class-definition is separated from the actual code, eg. having a .h and a .cpp file, the tests begin to fail. Additionally, reproducing EXMAPLE 4 of perlxstut (including a pure c lib with separate .h and .c files, no c++) works just fine.

    Conclusion:

    From what I see, the problem is somewhere located in the process where libmyclass.a is bound into Mytest.so, or in the creation of libmyclass.a itself.

    PS: This is my first time posting something on perlmonks, and writing about your problem really hepls to think about it.wow. Any maybe this thread will help another lost XS-Soul on their journey...feels good, man :D