GNOME Bugzilla – Bug 664284
Compiler errors for non-typedef'd delegates in existing C code
Last modified: 2018-05-19 21:14:09 UTC
When working on #663633, I noticed a problem that has cropped up in other VAPIs. The following code will fail to compile: void main() { Posix.GlobErrorFunction f; } GlobErrorFunction is the delegate of errfunc from glob: int glob(const char *pattern, int flags, int (*errfunc) (const char *epath, int eerrno), glob_t *pglob); The problem is that it was never typedef'd. As I see it, there are four options: Option 1) Modify the existing C code. -- This is not always possible. Option 2) Include a supplemental header file with the missing definitions. This can be done, but there isn't a good infrastructure for dealing with this (do they go in the vapidir? should the vapidir be given as an include dir to the compiler?) and it means duplicating the definitions. Option 3) Change the ccode gen to emit code like: int(*f)(char*,int); in the above example. This would have to be the case for parameters and variable declarations. Option 4) Emit the typedef for external delegates in the generated code just like the compiler does for internal delegates. I have written a patch that does Option 4...I'm not sure it does it well though. It adds a CCode always_declare which overrides the externality check during code generation and causes the typedef to be emitted. I am not sure, but I suspect it would be possibly to multiply emit that typedef once header files or not emit it in the right places. Is there a better way to do this?
Created attachment 201598 [details] [review] first attempt to force declaration of anonymous delegates from C code
Also for note, I've been working on libgit2 binding and tried option 1: https://github.com/libgit2/libgit2/pull/483 They would prefer options 3 or 4.
It's better option 3 by fixing the bug in producing the code for the anonymous function pointer. In particular see bug 621220. The patch there still needs some improvement.
Okay. I don't understand how bug 621220 is relevant. Here's a version that creates ret(*name)()-style function parameters, global declarations, local variables, temporary variables and fields. I've chosen to to make the argument list empty because there doesn't seem to be an easy way to use existing code to generate the parameter list as a string and it is still valid C without the parameter list. Should this get an arglist? If so, how to generate it? The other problem with generating is the following valid code would recurse infinitely: [CCode(anonymous_delegate = true)] public delegate int Foo(Foo f); There are situations where accessing the CCode attributes is done different. I'm not sure if there is a preference, but I've tried to follow local convention. Please advise. I've also attached some sample code that generates various anonymous delegates using the Posix.GlobErrorFunction.
Created attachment 201705 [details] [review] Create anonymous delegates for C function pointers which are not typedef'd
Created attachment 201706 [details] sample code to generate various delegates Must be compiled with --pkg posix
Simply cname="(*...the signature)". And it depends on that bug.
After discussion on IRC: Luca suggested something like: [CCode(cname = "int(*)()")] delegate int GlobErrorFunc(string s, int i); GlobErrorFunc foo; The problem is that it generates the incorrect C code: int(*)() foo; Because of that awful declaration-reflects-use thing, it has to be defined as: int(*foo)(); Furthermore, the last patch I submitted is buggy when it comes to high-order types. For instance: GlobErrorFunc[] myfuncs; should be: int(*myfuncs[])(); but my code will generate: GlobErrorFunc* myfuncs; The same is true for pointers. Obviously, I can combine these things into nice monsters. Making Option 4 work properly would require changing the idea that every declaration is an independent type and name that are, more or less, declared by "${type} ${name};".
*** This bug has been marked as a duplicate of bug 794920 ***