English Amiga Board

English Amiga Board (https://eab.abime.net/index.php)
-   Coders. C/C++ (https://eab.abime.net/forumdisplay.php?f=118)
-   -   fd2pragma inline entry for function that returns pointer to another function (https://eab.abime.net/showthread.php?t=109956)

Sim085 28 February 2022 07:55

fd2pragma inline entry for function that returns pointer to another function
 
In my dynamic library I have added a function that returns a pointer to another function. The function to be returned has the following signature;
Code:

int func(int,int)
So in my clib mylib_proto file I have the following entry;
Code:

int (*getMyFunction())(int,int);
The problem is that when generating the inline, fd2pragma creates the following;
Code:

int (*)(int,int) __getFunction(__reg("a6") struct Library *)="\tjsr\t-36(a6)";
#define getFunction() __getFunction(MyLibBase)

However, for this to work I need it to generate the following syntax;
Code:

int (*__getFunction(__reg("a6") struct Library *))(int,int)="\tjsr\t-36(a6)";
#define getFunction() __getFunction(MyLibBase)

I have gone through the fd2pragma guide and I cannot find anything specific in relation to this. Anyone knows if it is possible?

phx 28 February 2022 14:19

This is certainly a bug in fd2pragma, but not trivial to fix.
Usually such function pointer types are avoided in dynamic libraries. Or simply replaced by
APTR
.
I would suggest to define the function pointer return value type with a
typedef
in your clib header:
Code:

typedef int (*MYFUNCTYPE)(int,int);
Then you can declare the function's prototype as
Code:

MYFUNCTYPE getFunction(void);
and fd2pragma might have less problems to generate correct code (it is more readable too).

Sim085 28 February 2022 14:49

Using typedef is the first thing that I tried. However it seems fd2pragma does not support that as it gave me an error. Reading the documentation I found the following;

"fd2pragma knows all standard parameter types defined in exec/types.h and dos/dos.h, all structures and some more types. All other #typedef's bring a warning. Do not use them in prototypes files!"

This is why I then took the other approach.

Quote:

Originally Posted by phx (Post 1534239)
This is certainly a bug in fd2pragma, but not trivial to fix.
Usually such function pointer types are avoided in dynamic libraries. Or simply replaced by
APTR
.
I would suggest to define the function pointer return value type with a
typedef
in your clib header:
Code:

typedef int (*MYFUNCTYPE)(int,int);
Then you can declare the function's prototype as
Code:

MYFUNCTYPE getFunction(void);
and fd2pragma might have less problems to generate correct code (it is more readable too).


phx 28 February 2022 18:12

Quote:

Originally Posted by Sim085 (Post 1534250)
All other #typedef's bring a warning. Do not use them in prototypes files!"

But it's just a warning. Does it work, or not? :)
Otherwise you could still add the new typedef to
fd2pragma.types
.

Sim085 28 February 2022 19:56

No it doesn't :(

It gives a warning and says it is going to handle the typedefs as int and then says it cannot find the prototype functions and finally says empty or partial file deleted. In short the inline file is not generated.

Quote:

Originally Posted by phx (Post 1534303)
But it's just a warning. Does it work, or not? :)

I tried add the following to fd2pragma.types

"MYFUNCTYPE : int (*)(int,int)"

It does not seem to have worked. To be honest not a big fan of this solution as that would mean having to edit fd2pragma.types each time if trying to build on a new environment (at the moment placed it in C).

Quote:

Originally Posted by phx (Post 1534303)
Otherwise you could still add the new typedef to
fd2pragma.types
.


Sim085 28 February 2022 21:41

I think I will try and avoid them as well :)



Quote:

Originally Posted by phx (Post 1534239)
Usually such function pointer types are avoided in dynamic libraries.


phx 01 March 2022 10:49

Quote:

Originally Posted by Sim085 (Post 1534322)
It gives a warning and says it is going to handle the typedefs as int

Which wouldn't be a big problem, because for the assembler code it doesn't matter if the d0 register returns an int or a function pointer. It's both a 32-bit value.

Quote:

and then says it cannot find the prototype functions
Then you have an error in your clib prototype header.

Now I was curious and tried to reproduce it. Using the following clib header and FD file:
Code:

frank@nerthus cat clib/my_protos.h
typedef int (*MYFUNCTYPE)(int,int);

MYFUNCTYPE GetFunction(void);
frank@nerthus cat my_lib.fd
##base _MyBase
##bias 30
##public
GetFunction()()
##end

Then generate the proto header with fd2pragma. There are some warnings, as expected, but the result is looking good:
Code:

frank@nerthus fd2pragma -s 38 -c clib/my_protos.h -i my_lib.fd
SourceFile: my_lib.fd
Warning 46 : Missing the types definition file. Using internal defaults.
Warning 80 in line 1 of clib file: Unknown type of return value (typedef) handled as int.
Warning 79 in line 1 of clib file: Unknown type of argument 1 (MYFUNCTYPE) handled as int.
ResultFile: my.h
frank@nerthus cat my.h
#ifndef _PROTO_MY_H
#define _PROTO_MY_H

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif
#if !defined(CLIB_MY_PROTOS_H) && !defined(__GNUC__)
#pragma stdargs-on
#include <clib/my_protos.h>
#pragma stdargs-off
#endif

#ifndef __NOLIBBASE__
extern struct Library *MyBase;
#endif

#ifdef __GNUC__
#ifdef __AROS__
#include <defines/my.h>
#else
#include <inline/my.h>
#endif
#elif defined(__VBCC__)
#ifndef _NO_INLINE
#include <inline/my_protos.h>
#endif
#else
#include <pragma/my_lib.h>
#endif

#endif  /*  _PROTO_MY_H  */

Same for the assembler inline header:
Code:

frank@nerthus fd2pragma -s 70 --voidbase -c clib/my_protos.h -i my_lib.fd
SourceFile: my_lib.fd
Warning 46 : Missing the types definition file. Using internal defaults.
Warning 80 in line 1 of clib file: Unknown type of return value (typedef) handled as int.
Warning 79 in line 1 of clib file: Unknown type of argument 1 (MYFUNCTYPE) handled as int.
ResultFile: my_protos.h
frank@nerthus cat my_protos.h
#ifndef _VBCCINLINE_MY_H
#define _VBCCINLINE_MY_H

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

MYFUNCTYPE __GetFunction(__reg("a6") void *)="\tjsr\t-30(a6)";
#define GetFunction() __GetFunction(MyBase)

#endif /*  _VBCCINLINE_MY_H  */


bebbo 01 March 2022 11:55

Maybe you could switch to sfdc and provide sfd files...

Code:

==base FooBase
==basetype struct Library *
==libname foo.library
==bias 42
==public

* Functions...
void * foo(void (*fx)(int, int *)) (a1)

sfdc --target=m68k-amigaos --mode=macros x.sfd
Code:

#define foo(___fx) \
      LP1FP(0x2a, void *, foo , __fpt, ___fx, a1,\
      , FOO_BASE_NAME, void (*__fpt)(int,int * ))

sfdc --target=m68k-amigaos --mode=clib x.sfd
Code:

void * foo(void (* fx)(int,int * ));

phx 01 March 2022 14:00

Quote:

Originally Posted by bebbo (Post 1534421)
Maybe you could switch to sfdc and provide sfd files...

Nice to see that sfdc doesn't suffer under the same function pointer bug, but that probably won't help him as it can only output gcc headers and has heavy dependencies, like Perl.

bebbo 01 March 2022 16:10

Quote:

Originally Posted by phx (Post 1534438)
Nice to see that sfdc doesn't suffer under the same function pointer bug, but that probably won't help him as it can only output gcc headers and has heavy dependencies, like Perl.


oh, ok...


projects/sfdc/sfdc --target=m68kvbcc-amigaos --mode=macros x.sfd
Code:

#ifndef _INLINE_FOO_H
#define _INLINE_FOO_H

#ifndef _SFDC_VARARG_DEFINED
#define _SFDC_VARARG_DEFINED
#ifdef __HAVE_IPTR_ATTR__
typedef APTR _sfdc_vararg __attribute__((iptr));
#else
typedef ULONG _sfdc_vararg;
#endif /* __HAVE_IPTR_ATTR__ */
#endif /* _SFDC_VARARG_DEFINED */

void * __foo(__reg("a6") struct Library * , __reg("a1") void (* fx)(int,int * ) ) = "\tjsr\t-42(a6)";
#define foo(fx) __foo(FooBase, (fx))

void * __faa(__reg("a6") struct Library * , __reg("d0") int x , __reg("a1") void (* fx)(int,int * ) , __reg("a2") char * p ) = "\tjsr\t-48(a6)";
#define faa(x, fx, p) __faa(FooBase, (x), (fx), (p))

#endif /* !_INLINE_FOO_H */


Sim085 01 March 2022 22:13

I have copied the exact code and its failing :(
I am running fd2pragma on workbench 3.1 - would that make any difference?



Quote:

Originally Posted by phx (Post 1534413)
Now I was curious and tried to reproduce it.


phx 02 March 2022 10:38

Quote:

Originally Posted by bebbo (Post 1534458)
--target=m68kvbcc-amigaos

Wow... that's new, isn't it?
So there is an alternative! Nice.

Quote:

Originally Posted by Sim085 (Post 1534514)
I have copied the exact code and its failing :(
I am running fd2pragma on workbench 3.1 - would that make any difference?

Don't think so. It also works under AmigaOS and MorphOS:
Code:

Ram Disk:> fd2pragma special 38 clib clib/my_protos.h my_lib.fd
SourceFile: my_lib.fd
Warning 80 in line 1 of clib file: Unknown type of return value (typedef) handled as int.
Warning 79 in line 1 of clib file: Unknown type of argument 1 (MYFUNCTYPE) handled as int.
ResultFile: my.h

Do you have the latest fd2pragma from here?
http://phoenix.owl.de/fd2pragma.tar.gz
Or alternatively from the recent vbcc V0.9h binary archive.

You can also try sfdc, as we learned from Bebbo, in case you have a cross-compiling environment with Perl installed somewhere.
Nowadays you should prefer SFD files over FD anyway.


All times are GMT +2. The time now is 19:55.

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.

Page generated in 0.08938 seconds with 11 queries