Mailing List Archive

C++/perl/xsubpp
Forwarded to perl5-porters.

----- Begin Included Message -----

From: Mike Bright <mjb@speedy.grenoble.hp.com>
Subject: C++/perl/xsubpp
To: petheram@acm.org, P.B.Schuller@cuci.nl, jeffrey@best.com,
olson@mcs.anl.gov, Tim.Bunce@ig.co.uk, syost@atria.com
Date: Wed, 13 Dec 95 20:11:40 MET
Os: HP-UX tnoscp08 A.09.05 E 9000/715 2007787655 8-user license


Hi Guys,

Sorry for the lack of netiquette BUT ... I really think you could help me
and others in the perl community. I'm willing to write up this method if
someone will just give me that small ammount of info I need.

I saw your names associated with perl modules written in C++, according to
the Perl5 module list.

I have been trying to interface perl and C++ using xsub.
I've tried to figure it out for myself and know that I'm really close
but I still need a basic example to fill in the gaps - see below.
I've asked several times on notes but at best people tell me look at the
perlapi man page. That's a joke. I figured out how to link with
C++ from there - no mean feat - but understanding how to generate C++
objects AND invoke their instance methods form perl .. no info!

I've seen several other people trying to do the same but NOONE has ever
posted an example. I've searched on CPAN sites for your code but each
one of you is referenced by your e-mail address only - your software
was not archived.

WHAT I'D LIKE, please:

A simple example comprising of

<module>.xs, <module>.pm, test.pl

to show how a C++ library file can be interfaced to so that some
C++ class can be accessed from perl in the form:

$instance = mypackage::new;
$instance->invokeMypackMethod();

or something similar, including any "blessing".

I can provide my meager attempts for you to laugh at/correct. You'll see that
I'm really very close (and also very far away).
I've included this. You should only really find
xsttest.pl xstcc/xstcc.pm xstcc/xstcc.xs to be of interest.



--------------------------------------------------------------------------------
In-Real-Life: Michael Bright
Organisation: Hewlett-Packard Grenoble, Telecom Networks Operation
Address: 5, ave Raymond Chanas, 38053 Eybens, FRANCE
Telephone: [+33] 76 62 58 23 FAX 76 62 14 88
E-Mail: Michael_Bright@grenoble.hp.com mjbright@msn.com
S=mjb;OU1=grenoble;OU2=unix;O=hp;P=hp;A=ATLAS 400;C=FR




# This is a shell archive. Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by BRIGHT Michael <mjb@tnoscp08> on Wed Dec 13 20:08:23 1995
#
# This archive contains:
# xsttest.pl xstcc/xstcc.pm
# xstcc/xstcc.xs xstcc/Makefile.PL
# xst.h xst.C
#

LANG=""; export LANG
PATH=/bin:/usr/bin:$PATH; export PATH

echo x - xsttest.pl
cat >xsttest.pl <<'@EOF'


use xstcc;

# Works OK : invoking static function of class testXs in package xstcc
printf("Call testfn:\n");
$ret = &xstcc::testfn();
print "Return value = ", $ret, "\n";

# Doesn't work:
printf("Call new xstcc::testXs\n");
$ret = xstcc::new;
print "Return value = ", $ret, "\n";

print "0\n";
bless $ret,xstcc;
print "blessed Return value = ", $ret, "\n";
xstcc::calltest($ret);
$ret->calltest($ret);
print "1\n";
xstcc::calltest();
print "2\n";
$ret->xstcc::calltest();

printf("Call callnew:\n");
$ret = &xstcc::callnew();
print "Return value = ", $ret, "\n";

#testXs::testXs("sdj");
#testXs_new("sdj");
#&testXs::new();

@EOF

chmod 644 xsttest.pl

echo x - xstcc/xstcc.pm
sed 's/^@//' >xstcc/xstcc.pm <<'@EOF'
package xstcc;

require Exporter;
require DynaLoader;

@@ISA = qw(Exporter DynaLoader);
# Items to export into callers namespace by default. Note: do not export
# names by default without a very good reason. Use EXPORT_OK instead.
# Do not simply export all your public functions/methods/constants.
@@EXPORT = qw(

);
bootstrap xstcc;

# Preloaded methods go here.

testXs::testXs;
testXs::testme;
testXs::aStaticFn;

# Autoload methods go after __END__, and are processed by the autosplit program.

1;
__END__
@EOF

chmod 644 xstcc/xstcc.pm

echo x - xstcc/xstcc.xs
cat >xstcc/xstcc.xs <<'@EOF'
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

#include <./xst.h>

//#include <stream.h>
#include <stdio.h>


MODULE = xstcc PACKAGE = xstcc


char*
testfn()
CODE:
{
char *L_ret = new char(20);
strcpy(L_ret, "A string to return\n");

//cout << "xstcc::testfn()\n";
printf("xstcc::testfn()\n");

printf("xstcc::testfn() Calling testXs::aStaticFn()\n");
testXs::aStaticFn();

//printf("xstcc::testfn() Calling testXs::testme()\n");
//testXs::testme(39, "called from xstcc::testfn()");

RETVAL = L_ret;
}
OUTPUT:
RETVAL

void*
new()
CODE:
{
testXs* myTestXs;

printf("xstcc::new\n", items);
printf("Create new testXs (items==%d)\n", items);
fflush(stdout);

myTestXs = new testXs;

printf("Created new testXs:0x%x\n", myTestXs);
fflush(stdout);

//printf("Call sv_setref_pv\n");
//fflush(stdout);
//sv_setref_pv(ST(0), "xstcc::testXs", (void*) myTestXs);

printf("Calling sv_setptrobj()\n");
fflush(stdout);

ST(0) = sv_newmortal();
//ST(0) = sv_2mortal(newSVnv(myTestXs));
sv_setptrobj(ST(0), (void*) myTestXs, "xstcc:testXs");
printf("Called sv_setptrobj()\n");
fflush(stdout);



RETVAL = myTestXs;
//XSRETURN(1);
}


void*
callnew()
CODE:
{
testXs* myTestXs;

printf("Create new testXs (items==%d)\n", items);
fflush(stdout);

myTestXs = new testXs;

printf("Created new testXs:0x%x\n", myTestXs);
fflush(stdout);

sv_setref_pv(ST(0), "xstcc::testXs", (void*) myTestXs);
RETVAL = myTestXs;
//XSRETURN(1);
}


void
calltest()
CODE:
{
IV tmp;
testXs* THIS;

printf("calltest()\n");
fflush(stdout);

printf("set tmp\n");
fflush(stdout);
tmp = SvIV((SV*)SvRV(ST(0)));

printf("set THIS\n");
fflush(stdout);
THIS = (testXs *) tmp;


printf("THIS: 0x%x\n", THIS);
fflush(stdout);

printf("call testXs::testme()\n");
fflush(stdout);

THIS->testme(47, "Called form xstcc::calltest()\n");
printf("called testXs::testme()\n");
fflush(stdout);
}



@EOF

chmod 644 xstcc/xstcc.xs

echo x - xstcc/Makefile.PL
sed 's/^@//' >xstcc/Makefile.PL <<'@EOF'
use ExtUtils::MakeMaker;
# See lib/ExtUtils/MakeMaker.pm for details of how to influence
# the contents of the Makefile that is written.

# C version:
# cc -c -D_POSIX_SOURCE -D_HPUX_SOURCE -Aa +O1 +z -I..perl5/hpux/CORE -I.. xst.c

sub MY::xs_c {
'
@.xs.c:
$(PERL) $(XSUBPP) -C++ $(XSUBPPARGS) $*.xs >$*.tc && mv $*.tc $@
';
}

#$(PERL) $(XSUBPP) -C++ $(XSUBPPARGS) $*.xs >$*.tc && mv $*.tc $@

sub MY::c_o {
my(@m);
push @m, '
@.c.o:
CC -c $(CCCDLFLAGS) -I$(PERL_INC) $(DEFINE) $(INC) $*.c
';
join "", @m;
}

WriteMakefile(
'NAME' => 'xstcc',
'VERSION' => '0.1',
'LIBS' => ['-L.. -lxstest -lcxx -L/usr/lib -lC'], # e.g., '-lm'
'DEFINE' => '', # e.g., '-DHAVE_SOMETHING'
'INC' => '-I..', # e.g., '-I/usr/include/other'
);
#'LIBS' => ['-L.. -lxstest -L/usr/lib -lcxx -lC -lcxx'], # e.g., '-lm'
#'LIBS' => ['-L.. -lxstest -L/usr/lib -lC -lcxx'], # e.g., '-lm'
@EOF

chmod 644 xstcc/Makefile.PL

echo x - xst.h
cat >xst.h <<'@EOF'



class testXs {
public:
testXs();

int testme(int P_int, char* P_str);

static aStaticFn();

private:
int inst;
static int staticinst;
};

@EOF

chmod 644 xst.h

echo x - xst.C
cat >xst.C <<'@EOF'

#undef cpp

#ifdef cpp
# include <stream.h>
#else
# include <stdio.h>
#endif

#include <xst.h>

testXs::testXs()
{
return;
#ifdef cpp
cout << "Hello from testXs constructor\n"
<< "Created instance " << staticinst
<< "of class testXs\n";
cout.flush();
#else
printf("Hello from testXs constructor\n");
printf("Created instance %d of class testXs\n", staticinst);
fflush(stdout);
#endif
staticinst++;
inst=staticinst;

}


int
testXs::testme(int P_int, char* P_str)
{
#ifdef cpp
cout << "testXs::testme(P_int=" << P_int
<< ", P_str=" << P_str << "\n";
cout << "testXs::testme() on instance " << inst << "\n";

cout << "testXs::testme() returning:" << P_int+1 << "\n";
cout.flush();
#else
printf("testXs::testme() on instance %d\n", inst);
printf("Hello(%d) from %s\n", P_int, P_str);
fflush(stdout);
#endif
return P_int++;
}


int
testXs::aStaticFn()
{
#ifdef cpp
cout << "testXs::aStaticFn ==> currently " << staticinst
<< " instances\n";
cout.flush();
#else
printf("testXs::aStaticFn ==> currently %d instances\n", staticinst);
fflush(stdout);
#endif

return staticinst;
}



@EOF

chmod 644 xst.C

exit 0


----- End Included Message -----