For the C gurus,
c2nim translates
typedef int fv( int );
typedef int *pfv( int );
typedef int (*pfv2)( int );
int xfv( int );
int *pxfv( int );
int (*pxfv2)( int );
to
type
fv* = proc (a2: cint): cint
pfv* = proc (a2: cint): ptr cint
pfv2* = proc (a2: cint): cint
proc xfv*(a2: cint): cint
proc pxfv*(a2: cint): ptr cint
var pxfv2*: proc (a2: cint): cint
Shouldn't the pfv2 and pxfv2 function pointers be translated to
type
pfv2* = proc (a2: cint): ptr cint
proc pxfv2*(a2: cint): ptr cint
(ie, return a ptr cint) ? no, the c2nim translation is correct for pfv2 and pxfv2.
not correct for fv and pfv(cannot be translated to nim)
you should know that in C a pointer to a function and a function are equivalent. So these should produce the same result:
typedef int f0( int );
typedef int (*f1)( int );
typedef int (**f2)( int );
typedef int (***f3)( int );
typedef int (****f4)( int );
typedef int (*****f5)( int );
typedef int (******f6)( int );
typedef int (*******f7)( int );
But c2nim can't handle **, but on the other side it doesn't really matter that much, since that type is not really relevant.
and this is actually a function that returns an int*, because * binds to int, not pfv.
typedef int *pfv( int );
so c2nim is correct
The c2nim translation posted by jlp765 is correct. But i found something wrong when c2nim try to translate the usage of the typedefed type. Sorry not to mention them earlier.
typedef int xxx(int yyy);
xxx abc;
void zzz(xxx* f);
void www(xxx f);
zzz and www should produce the same result because they are equivalent. abc should be function declaration, but see how c2nim translate them:
type
xxx* = proc (yyy: cint): cint
var abc*: xxx #wrong, should be proc abc(yyy: int): cint
proc zzz*(f: ptr xxx) #wrong
proc www*(f: xxx)
imagine if this is used to importc something, crash will it be
var abc*: xxx #wrong, should be proc abc(yyy: int): cint
No, that is a correct translation.
proc zzz*(f: ptr xxx) #wrong
I don't know about this. I suppose the typedef is "ignored" as an abstraction and it really means "single pointer to function", not a "pointer to a function pointer" but somebody needs to ask GCC about this.
C is only easy when you are ignorant about lots and lots of details. ;-)
@Araq
Oh sorry, you are right, it was the other way around, because f0 and f1 are identical, you can dereference a function pointer arbitrarily often. Every time you dereference the pointer, the function is again equivalent to the pointer to it.
Please be patient with me. This may sound crazy, but this little experiment will tell us some --perhaps inconsistencies in C language.
typedef int xxx(int yyy);
xxx abc;
int main() {
abc(0);
return 0;
}
altough abc looks like a variable declaration, both gcc and vcc says it is a function declaration. here is the output of gcc and vcc:
gcc:
C:\Users\Jangko\AppData\Local\Temp\ccJu7Cm2.o:abc.c:(.text+0x13): undefined reference to `abc'
collect2.exe: error: ld returned 1 exit status
vcc:
abc.obj : error LNK2019: unresolved external symbol _abc referenced in function _main
abc.exe : fatal error LNK1120: 1 unresolved externals
if we change the C code a little bit with additional *:
typedef int xxx(int yyy);
xxx* abc;
int main() {
abc(0);
return 0;
}
both gcc and vcc will silent, because they accept abc as a variable declaration. of course, if you run the produced executables, it will crash.
now xxx will be used as argument type.
#include <stdio.h>
typedef int xxx(int yyy);
int pineapple(int yyy) {
return yyy + 13;
}
void apple(xxx n) {
printf("%d\n", n(1));
}
void banana(xxx* n) {
printf("%d\n", n(2));
}
int main() {
apple(pineapple);
banana(pineapple);
return 0;
}
again both vcc and gcc agree that n with type xxx or xxx* is equivalent, but inconsistent with the first abc.
from this little experiment, I think altough c2nim translation looks correct, but gcc and vcc don't agree that xxx abc; is a variable declaration.
In case of banana argument syntax, c2nim will produce proc banana*(n: ptr xxx). But how this proc can be usable? something like banana(pineapple), banana(pineapple.addr), or banana(pineapple.unsafeaddr) will be rejected by Nim compiler.
if we use something like:
var f: xxx = pineapple
banana(f.addr)
this is accepted by the compiler, but totally wrong if banana is imported from C.
Personally, i never encountered C library written like this, perhaps it is safe to assume very little chance for c2nim to encounter such code, but at least c2nim should warn the user if it does see code like this or we should document this peculiar C behaviour in c2nim documentation.