in reply to Re^3: Including existing C or CPP library using Inline
in thread Including existing C or CPP library using Inline

Hi Rob,

Here's the code I mentioned in my previous post. The 'add' function works properly if I execute it, whereas calling 'doSSW' results in a "Undefined subroutine" error. Thus my guess is that the issue lies with passing Perl strings to a C++ function.

Best, René
#!/usr/bin/perl use warnings; use Inline CPP => Config => BUILD_NOISY => 1, CLEAN_AFTER_BUILD => 0; use Inline CPP => Config => AUTO_INCLUDE => '#include "ssw_cpp.h"'; use Inline CPP; my $ref = "CAGCCTTTCTGACCCGGAAATCAAAATAGGCACAACAAA"; my $seq = "CTGAGCCGGTAAATC"; print add(3,5)."\n"; my $returned = cprintit($seq); print $returned."\n"; #my $cigar = do_SSW($seq,$ref); #print "$cigar\n"; __END__ __CPP__ using namespace std; string do_SSW(const char* queryC, const char* refC) { Inline_Stack_Vars; string query(queryC); string ref(refC); StripedSmithWaterman::Aligner aligner; StripedSmithWaterman::Filter filter; StripedSmithWaterman::Alignment alignment; aligner.Align(query.c_str(), ref.c_str(), ref.size(), filter, &ali +gnment); return alignment.cigar_string; } int add (const int a, const int b) { int c = a+b; return c; } int cprintit(const string seq) { cout << seq << endl; return 10; }

Replies are listed 'Best First'.
Re^5: Including existing C or CPP library using Inline
by syphilis (Archbishop) on Mar 22, 2014 at 07:49 UTC
    Thus my guess is that the issue lies with passing Perl strings to a C++

    I think it might have more to do with the way that the string has been passed.
    For example, cprintit() works fine if you rewrite it as:
    int cprintit(const char * seq) { cout << seq << endl; return 10; }
    That's how you've passed the strings to do_SSW() - the problem with do_SSW() is that you've specified a *return* of type "string".
    Perl's typemapping doesn't handle passing of the "string" type (either as argument or as return). You'll need to provide a typemap for "string" if you want to pass that type around.
    What happens if you specify a return type of "char *" (instead of "string") for do_SSW() ?

    For a solution using a typemap, this works for me:
    #!/usr/bin/perl use warnings; use Inline CPP => Config => BUILD_NOISY => 1, TYPEMAPS => 'C:/_32/pscrpt/inline-cpp/stringtype.map', CLEAN_AFTER_BUILD => 0; use Inline CPP; my $seq = "CTGAGCCGGTAAATC"; my $returned = cprintit($seq); print $returned."\n"; __END__ __CPP__ using namespace std; int cprintit(string seq) { cout << seq << endl; return 10; }
    where 'C:/_32/pscrpt/inline-cpp/stringtype.map' contains the following single line (plus newline):
    string T_PV
    (Safest to provide a fully qualified path to the typemap file - though a path relative to the cwd should also work.)

    Cheers,
    Rob
      Hi Rob, This indeed fixed the issue thank you very much! Here's the revised code:
      #!/usr/bin/perl use warnings; use Inline CPP => Config => BUILD_NOISY => 1, CLEAN_AFTER_BUILD => 0, TYPEMAPS => './stringtype.map'; use Inline CPP; my $seq = "CTGAGCCGGTAAATC"; my $ref = "CTGTGCCATGCGACTGGTACAATC"; my $cigar = do_SSW($seq,$ref); print "$cigar\n"; __END__ __CPP__ using namespace std; #include <string> #include "ssw_cpp.h" #include "ssw_cpp.cpp" #include "ssw.c" #include "ssw.h" char *do_SSW(string queryC, string refC) { StripedSmithWaterman::Aligner aligner; StripedSmithWaterman::Filter filter; StripedSmithWaterman::Alignment alignment; aligner.Align(queryC.c_str(), refC.c_str(), refC.size(), filter, & +alignment); string s = alignment.cigar_string.c_str(); char *a = new char[s.size()+1]; a[s.size()] = 0; memcpy(a,s.c_str(),s.size()); return a; }

      Having solved this problem, I am of course facing the next one: since the C++ alignment object contains more information and cannot be fully passed back to Perl right away, I am now trying to find a way to do so. My backup plan is to just concatenate all this information and then split the returned string in Perl.

      Anyhow, again thanks a lot! René

        You can always return an SV* containing a reference to an array, hash, or some complex data structure, if that is more useful.

        Since you're using Inline::CPP, you could also encapsulate the data in a class and provide accessors to each component of the data.


        Dave