For instance:
typedef void (*rtnvoid_args) ();
typedef void (*rtnvoid_args32) ( int );
typedef void (*rtnvoid_args32_32)( int );
typedef int (*rtn32_args32_32) ( int,int);
typedef int (*rtn32_args64_32) ( double,int);
typedef double (*rtn64_args64_32) ( double,int);
// define a bunch of function types
op callcfunc(IN PMC, IN STR, OUT INT, IN INT, IN INT) {
// $1 dynamic lib pmc
// $2 sub name
// $3 return value
// $4-5 args
char* name = string_to_cstring(interpreter, ($2));
rtn32_args32_32 fcn = (rtn32_args32_32) D2FPTR(Parrot_dlsym(($1)->data,
name));
$3 = fcn($4,$5);
goto NEXT();
}
Bytecode:
loadlib P1, "libyourdynamic.so"
set S0, "yourmethodname"
set I2, 8
set I3, 10
# I1 = yourmethodname(I2,I3)
callcfunc P1, S0, I1, I2, I3
print "\nReturned"
print I1
Ofcourse this could be adapted to support parrot calling conventions.
This way cuts out the need to parse "iii" style signatures and gets you
to calling C in just 2 steps. I think it might be a little faster too.
If you guys like this, I'll go ahead and devlop it further.
Michael W. Collins
nci is primarily for calling existing C routines -- namely, C routines
that are completely unaware of Parrot and use native types and
conventions. It can also be used for what it sounds like you're after,
which is implementing Parrot ops or PMC methods in C, but that's a
subset of its full intention.
I would imagine that implementing PMC methods via dynamically loaded
routines would have more core support -- something to create a new PMC
vtable and fill in the slots, perhaps? You'd probably only use the
existing dynamic stuff, not anything nci-specific, because all methods
would have a particular C signature, so there's no reason to deal with
figuring out what type of function you're calling.
Dynamically loaded ops are another thing, and will need yet another
mechanism of some sort -- but again, all ops have the same C
signature, so they'll only share dynamic loading too. (Or maybe not
even that?)
Did I misunderstand your intent?
Right now, you have to use:
dlfunc P0, P1, "method name", "iii"
invoke
This stores (into P0) an nci function that can HANDLE calling a C function.
My point is, I wonder if it would be easier to just call C functions
directly through my proposed "call_c_function" op bypassing the nci
system.
Nci has to parse the signature which stores an nci handler into a pmc.
The nci handler is responsible for calling your C function with
appropriate args and stores the return value.
I'm saying, take out the parse step, take out the nci handler and call C
functions using one op "call_c_function" which uses a bunch of typedefed
function pointers to do the same work that nci does only without the
parsing and extra handler functions.
so I propose:
call_c_function P0, S0, [I0, I1, I2]
where:
P0 = pmc pointing to your loaded .so file
S0 = name of the C method you want to call
Next arg = where to store the return value
Rest of args = arguments to the C function
It's the same functionality, only a little simpler ;)
Michael W. Collins
Well.... You'd think so. I did too, at the beginning, but there are a
couple of things that argue against it.
First, I did want native routines to be functionally
indistinguishable from parrot routines, which they are in the current
scheme. That way someone calling a sub in a PMC doesn't need to care
where it came from or what type it is, which makes sticking C
functions into the symbol table a lot easier. The invoke op is just a
subroutine call through a PMC, and there's nothing truly special
about it relating to C code.
Second, there's the issue of dynamic generation. While right now
there's a big mass of nasty stub functions generated for each known
signature type, it's perfectly possible and reasonable (and, in fact,
Leo's done it for the x86 :) to automatically create the interface
functions--it's what I want to do, long term. If you do the math,
you'll find that actually providing all the functions (or in this
case ops) for all the different combinations of args is non-trivial
in space terms. Even with only a few types of arguments (with no type
checking there are eight or ten) once you trigger that combinatorial
explosion, well, you get a lot of functions.
So it's a good idea, but one that turns out to be untenable. Yeah,
the current scheme is awkward and if we can replace it with something
less so, that'd be great, but unfortunately I think special ops for
each function call type aren't it.
--
Dan
--------------------------------------"it's like this"-------------------
Dan Sugalski even samurai
d...@sidhe.org have teddy bears and even
teddy bears get drunk