Pyd: Wrapping too many functions in a class gives a compiler error

Kirk McDonald kirklin.mcdonald at gmail.com
Fri Jul 6 12:06:11 PDT 2007


Simen Haugen wrote:
> I cannot wrap all the functions in my class without getting the compile 
> error:
> Error: identifier _D3pyd9func_wrap1172__T22app (...) is too long by x 
> characters.
> 
> And its several thousand characters too long...
> 
[snip]
>  wrap_class!(
>   NSD
>   , Init!(void function(char[], char[]))
>   , Def!(NSD.filter, "filter", Respondent[] function(char[]))
>   , Def!(NSD.filter, "filterResps", Respondent[] function(char[], 
> Respondent[]))
>   , Def!(NSD.countOf, "countOf", double function(char[]))
>   , Def!(NSD.countOf, "countOfResps", double function(char[], Respondent[]))
>   , Def!(NSD.getQuestion)
>   , Def!(NSD.getQuestionIds)
>   , Def!(NSD.getRespondent)
>   , Def!(NSD.numQuestions)
>   , Def!(NSD.respondents)
>   , Def!(NSD.writeasc)
>   , Def!(NSD.writensd)
>   , Def!(NSD.writesps)
>   , Def!(NSD.writecsv)
>   , Def!(NSD.clear)
>   , Property!(NSD.questions)
>  );
> }
[snip]

Curses. This is one of those things I knew would be a problem, but 
always just put off doing something about.

wrap_class is, of course, a template. It looks something like this:

void wrap_class(T, Params...)();

The problem with templates is that every template instantiated results 
in a mangled identifier being created in the object file. Identifiers 
have a maximum length, so when a big long one is created like this, it 
runs headlong into that maximum length. That variadic Params parameter 
is the perfect place to run into it, since each of the things you pass 
to it are fairly long in themselves.

I always knew this would be an issue, but I never tried explicitly 
testing for the maximum length.

Pyd's API wasn't always like this. It used to look like this:

wrapped_class!(Foo) f;
f.def!(Foo.bar);
f.def!(Foo.baz);
finalize_class(f);

This neatly side-steps any problems with maxiumum symbol lengths. 
However, by having all of the arguments in a tuple like the current API 
does, they are all available at compile-time, meaning I can use them to 
generate a subclass of T, and do some very fancy stuff with polymorphism.

Barring any changes to the language (such as macros or the compile-time 
reflection mechanisms I outlined in an earlier post), I basically one 
option for fixing this, which is to bring back the old API. This is not 
an attractive option, since then Pyd would basically have two APIs 
side-by-side. (If I ditch the current API, I lose the polymorphism stuff.)

This means that, when wrapping a big class, you'll either be able to 
have all of its methods, or the fancy polymorphism stuff, but not both. 
This annoys me, deeply.

In a perfect world, I'd have both of the following:

* Templates which do not generate symbols, if those symbols aren't 
actually needed. (Or some way for the user to specify a template's 
symbol is not needed.)

* The compile-time reflection stuff I've been talking about. With that, 
you'd just need to say:

wrap_class!(Foo);

(Although cases such as overloaded functions would still have to be 
covered somehow.)

That said, I will be looking into whether I can shorten those symbol 
names. I'm going to be banging my head against this for the next few 
days, I can tell.

-- 
Kirk McDonald
http://kirkmcdonald.blogspot.com
Pyd: Connecting D and Python
http://pyd.dsource.org



More information about the Digitalmars-d mailing list