Subject: Re: Vote on Kevin's proposal
From: Kevin Cameron (sv-xx@grfx.com)
Date: Sun Dec 22 2002 - 16:37:33 PST
> From: "Stickley, John" <john_stickley@mentorg.com>
>
> I vote "no" on accepting 1.1b in its current form
> mainly because,
>
> 1. I don't think dynamic binding is needed in first version
> of the C calling interface.
Did you discuss that with the CVE/Seamless team?
> 2. Even if it were, a significantly simpler dynamic binding
> scheme can be realized than what Kevin proposes.
Not really. If you make it simpler in one place it'll get more
complicated somewhere else.
> I would also like to say that I carefully went over Kevin's
> detailed examples on how the interface would be used.
>
> These examples demonstrate a complex technique for dynamically
> binding C++ functions where the code itself requires knowledge
> of the name mangling schemes of specific C++ compiler
> environments. This, in my view, is unacceptible.
You can take that issue to the ANSI committees. The point of
methodology in the proposal is it allows mixing libraries from
different compilers. You only need to write the name mangling
code once for any one compiler (and it may have been done
already).
> Here are my other main objections to it:
>
> 1. We don't need both a "call forward" "register locator"
> *and* a "call back" binding function. All we would need is
> a call forward binding function (i.e. svBind()).
You do if you want to link arbitrary C++ compilers code
dynamically.
> 2. The string parsing requirement for argument profiles
> is overly complicated and buys you very little. Plus
> it requires the code to have knowledge of C++ compiler
> name mangling schemes and even with this, there's no
> guarantee that the pointers to the functions being
> bound match the profiles of the extern definitions in
> the SV side. So really the type safety that it is
> attempting to create, falls well short of its goal.
There is a guarantee that if you have generated the type
strings properly, and the mangling is performed properly
the routine will match the profile. There is no other
proposal that offers any checking in this area.
> A static linking scheme that makes use of optional
> SV compiler generated headers provides superior type
> safety checking than Kevin's scheme does. The same
> overall goals of the example given by Kevin can
> alternately be accomplished using the static linking
> scheme.
Are mandating header generation?
That's not a link-time check, there is no guarantee that
the the code in the library matches correctly unless you
include all the code-generation rules.
Only C++ combines the argument types with the C name of
the routine, so only C++ comes close to guaranteeing that
your calls match.
> Here's how:
>
> 1. In SV code declare extern functions to Kevin's
> "foo" double and "foo" int functions:
>
> SV declarations:
> ----------------
>
> extern context "foo_double" integer foo( real arg );
> extern context "foo_int" integer foo( integer arg );
The "foo_double"/"foo_int" is extra over my proposal, the
locator works it out.
> In this case foo_double() and foo_int() are extern "C"
> linkage wrappers for the real overloaded C++ variants
> of these functions shown in Kevin's example.
>
> Now, on the C side, you can still use dlopen() and dlsym()
> to look up the functions as Kevin shows. But what you
> do is set pointers that the C wrappers call.
>
> Here you've created application level dynamic binding
> capability from static capability with very little
> added overhead and with no name mangling interpretation
> required.
>
> A better designed, more compact object oriented scheme
> could also be used but here I just used a rudimentry
> scheme to follow with the flow of Kevin's example.
>
> Optional SV compiler generated header sv_decls.h:
> -------------------------------------------------
>
> extern "C" {
> extern int foo_double( svHandle context, double arg );
> extern int foo_int ( svHandle context, int arg );
> };
>
> test.c:
> -------
>
> // Define pointers to the real C++ functions here:
> static int (*real_foo_double)( svHandle context, double arg );
> static int (*real_foo_int) ( svHandle context, int arg );
>
> // Define the wrappers here that will be directly called
> // from SV, which then call the real C++ functions.
> extern "C" {
> int foo_double( svHandle context, double arg ){
> return (*real_foo_double)( context, arg ); }
>
> int foo_int( svHandle context, int arg ){
> return (*real_foo_int)( context, arg ); }
>
> void (*bindMyFoos)( void *, void *); // "Locator" function pointer.
> };
>
> main(){
> // Dynamically load code library containing real functions:
> void *lib = dlopen("./liblib.so",RTLD_NOW); // Open dynamic library
>
> // Now look up and call "locator" function that, itself,
> // is an extern "C" function.
> bindMyFoos = dlsym(lib,"BindMyFoos");
> (*bindMyFoos)( (void *)&real_foo_double, (void *)&real_foo_int );
>
> ...
> }
Where did you tell SV to call "bindMyFoos" ?
> Dynamically loaded lib.cc:
> --------------------------
>
> // Here are the real C++ foo functions:
> int foo( svHandle context, double arg ) {
> fprintf(stderr,"Called (double)\n");
> return arg * ((user_struct *)(svGetUserData(context))->dbl;
> }
>
> int foo( svHandle context ,int arg ) {
> fprintf(stderr,"Called (int)\n");
> return arg * ((user_struct *)(svGetUserData(context))->data[0];
> }
>
> typedef int (*foo_double_type)(svContext context, double arg );
> typedef int (*foo_int_type) (svContext context, int arg );
>
> extern "C" {
> void BindMyFoos( void *real_foo_double, void *real_foo_int ){
> // This assignments will pick correct variants of foo
> // according to Stroustrup $r.13.3
Does that mean you didn't try it?
> *((foo_double_type *)real_foo_double) = &foo;
> *( (foo_int_type *)real_foo_int) = &foo;
> }
> };
You don't have the data setup phase.
> Note that this is just as efficient as Kevin's example with
> two added benefits:
>
> 1. No need for knowledge of compiler specific mangling schemes
But the user needs to add information in the "extern" declaration
to compensate.
> 2. No dynamic binding needed in DirectC API. Can be handled
> completely at application layer if required.
But that didn't buy you anything, you still have no real argument
checking, and the same number of indirections. And as a downside
you are using more of the C linker name space which will lead to
more name clashes.
I suggest you redo your example with the missing bits added (how
myBindFoos gets declared to SV, and how the contexts get initialized),
and give us a version that compiles and runs like mine did. Also,
where's your magic does-everything svBind call?
Kev.
> -- johnS
>
> Warmke, Doug wrote:
> > Team,
> >
> > I believe today is the deadline for voting on Kevin's proposal.
> > Kevin requested an extension this week but there was no reply
> > from either Ghassan or Swapnajit.
> >
> > If there is no extension, my vote on the proposal is "no".
> >
> > I feel the complexity is too high and therefore it is not
> > in the spirit of the original DirectC requirements,
> > "convenience and performance". Also the proposal is making
> > too many assumptions regarding the rest of SV 3.1 which
> > may or may not come true.
> >
> > Thanks for all the work you did on it, Kevin.
> > I'm sorry I couldn't go with you on this one.
> >
> > Regards,
> > Doug Warmke
>
> --
> __
> ______ | \
> ______________________/ \__ / \
> \ H Dome ___/ |
> John Stickley E | a __ ___/ / \____
> Principal Engineer l | l | \ /
> Verification Solutions Group | f | \/ ____
> Mentor Graphics Corp. - MED C \ -- / /
> 17 E. Cedar Place a \ __/ / /
> Ramsey, NJ 07446 p | / ___/
> | / /
> mailto:John_Stickley@mentor.com \ /
> Phone: (201)818-2585 \ /
> ---------
>
----- End Included Message -----
This archive was generated by hypermail 2b28 : Sun Dec 22 2002 - 16:38:37 PST