Thanks for your helpful suggestions.
Your example compiles and runs, but:
$ ldd aaa
linux-vdso.so.1 (0x00007ffd0e4c6000)
libperl.so.5.30 => /lib64/libperl.so.5.30 (0x00007fe9264b5000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fe926493000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007fe92648c000)
libc.so.6 => /lib64/libc.so.6 (0x00007fe9262c3000)
libm.so.6 => /lib64/libm.so.6 (0x00007fe92617d000)
libcrypt.so.2 => /lib64/libcrypt.so.2 (0x00007fe926142000)
So it is already linked to the perl shared library. If I remove -lperl from the link arguments I get:
in function `xs_init':
/home/jv/tmp/aaa.c:28: undefined reference to `PL_thr_key'
/bin/ld: /home/jv/tmp/aaa.c:28: undefined reference to `pthread_getspe
+cific'
/bin/ld: /home/jv/tmp/aaa.c:28: undefined reference to `Perl_newXS'
EDIT: Managed to get it going by adding a Perl_newXS function as follows:
CV* Perl_newXS(pTHX_ const char *name, XSUBADDR_t subaddr, const char
+*filename) {
CV* (*imp)(tTHX, const char*, XSUBADDR_t, const char*);
imp = (CV* (*)(tTHX, const char*, XSUBADDR_t, const char*)) dlsym( h
+andle, "Perl_newXS" );
return (*imp)(my_perl, name, subaddr, filename);
}
The complete proof-of-concept program is now:
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <EXTERN.h>
#include <perl.h>
void *handle; /* for dl */
static PerlInterpreter *my_perl;
void (*boot_DynaLoader)(pTHX_ CV* cv);
CV* Perl_newXS(pTHX_ const char *name, XSUBADDR_t subaddr, const char
+*filename) {
CV* (*imp)(tTHX, const char*, XSUBADDR_t, const char*);
imp = (CV* (*)(tTHX, const char*, XSUBADDR_t, const char*)) dlsym( h
+andle, "Perl_newXS" );
return (*imp)(my_perl, name, subaddr, filename);
}
void xs_init(pTHX) {
static const char file[] = __FILE__;
dXSUB_SYS;
PERL_UNUSED_CONTEXT;
newXS( "DynaLoader::boot_DynaLoader", boot_DynaLoader, file );
}
int main( int argc, char **argv, char **env ) {
/* open shared lib */
handle = dlopen("perl530.so", RTLD_LAZY);
if ( !handle ) {
fprintf( stderr, "%s\n", dlerror() );
exit(EXIT_FAILURE);
}
/* Get entry point for perl_alloc */
void* (*perl_alloc)();
perl_alloc = (void*(*)()) dlsym(handle, "perl_alloc");
/* Call perl_alloc */
my_perl = (*perl_alloc)();
/* perl_construct */
void (*perl_construct)(void*);
perl_construct = (void(*)(void*)) dlsym(handle, "perl_construct");
(*perl_construct)(my_perl);
/* boot_DynaLoader */
boot_DynaLoader = (void (*)(pTHX_ CV* cv)) dlsym(handle, "boot_DynaL
+oader");
/* perl_parse */
void (*perl_parse)(void*, void*, int, char**, char**);
perl_parse = (void(*)(void*, void*, int, char**, char**)) dlsym(hand
+le, "perl_parse");
(*perl_parse)(my_perl, xs_init, argc, argv, env);
/* perl_run */
int (*perl_run)(void*);
perl_run = (int(*)(void*)) dlsym(handle, "perl_run");
int result = (*perl_run)(my_perl);
/* perl_destruct */
void(*perl_destruct)(void*);
perl_destruct = (void(*)(void*)) dlsym(handle, "perl_destruct");
(*perl_destruct)(my_perl);
/* perl_free */
void(*perl_free)(void*);
perl_free = (void(*)(void*)) dlsym(handle, "perl_free");
(*perl_free)(my_perl);
return result;
}
Build with:
$(perl -MConfig -e 'print $Config{cc}') p.c $(perl -MExtUtils::Embed -e ccopts ) -o aaa -ldl -Wl,--rpath=.
Although it seems that dynamic loading is not yet functional... For example, this fails:
aaa -MFcntl=:flock -E "say 1+LOCK_NB"
Undefined subroutine &Fcntl::LOCK_NB called at -e line 1.