Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2009-05

How to call lib routines with cdecl calling convention with win32 app?

7 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Coco Pascal

I have a library with udf routines using the cdecl calling convention, required by Firebird. This seems to work well on win32. However when I test these routines with a fpc win32 app declaring external functions with the cdecl or stdcall calling convention gives me a 'entrypoint not found' error. I assume cdecl is obligatory, but can I implement that?

Marco van de Voort
to Coco Pascal

In our previous episode, Coco Pascal said:

I have a library with udf routines using the cdecl calling convention, required by Firebird. This seems to work well on win32.

How exactly?

However when I test these routines with a fpc win32 app declaring external functions with the cdecl or stdcall calling convention gives me a 'entrypoint not found' error. I assume cdecl is obligatory, but can I implement that?
Maybe it is a matter of an underscore prefix. Write the declaration full
(cdecl external libname name '_symbol';

and experiment with leaving the underscore there or not.

It might also be the need to declare a libname. Windows and OS X afaik have separate linker namespaces for external libs, so you need to declare the name of the module they are in.

Coco Pascal
to Marco van de Voort
Marco van de Voort wrote 8 lines
In our previous episode, Coco Pascal said: > I have a library with udf routines using the cdecl calling convention, > required by Firebird. This seems to work well on win32. > How exactly?

?

function Y_Odd(const AValue: Int64): LongInt; cdecl; export;
begin
  if Odd(AValue) then
    Result := -1
  else
    Result := 0;
end; {Y_Odd}

exports

Y_Odd;

This works fine with Firebird. If I declare the stdcall calling convention Firebird can't find its entrypoint.

Show quoted text 16 lines
> However when I test these routines with a fpc win32 app declaring > external functions with the cdecl or stdcall calling convention gives me > a 'entrypoint not found' error. I assume cdecl is obligatory, but can I > implement that? > Maybe it is a matter of an underscore prefix. Write the declaration full (cdecl external libname name '_symbol'; and experiment with leaving the underscore there or not. It might also be the need to declare a libname. Windows and OS X afaik have separate linker namespaces for external libs, so you need to declare the name of the module they are in.
   function Y_Odd(const AValue: Int64): LongInt; cdecl; external LibName
name 'libyfbudf.dll';
gives me an  Identifier not found "LibName" error.
   function Y_Odd(const AValue: Int64): LongInt; cdecl; external
'_libyfbudf.dll';
gives me a File not found _libyfbudf.dll.
Jonas Maebe
to Coco Pascal
Coco Pascal wrote 25 lines
Marco van de Voort schreef: > In our previous episode, Coco Pascal said: > >> I have a library with udf routines using the cdecl calling >> convention, required by Firebird. This seems to work well on win32. > > How exactly? > ? function Y_Odd(const AValue: Int64): LongInt; cdecl; export; begin if Odd(AValue) then Result := -1 else Result := 0; end; {Y_Odd} exports Y_Odd; This works fine with Firebird. If I declare the stdcall calling convention Firebird can't find its entrypoint.

cdecl automatically enables C-compiler-compatible name mangling for exported procedures. stdcall doesn't. So it's normal that Firebird does not find the entrypoint when using stdcall, as it does not support FPC-style name mangling.

There is no way to get C name mangling without the calling convention, so you have to manually declare an alias in that case. E.g.,

function Y_Odd(const AValue: Int64): LongInt; cdecl; alias: '_Y_Odd'; export;

Whether or not you need an extra underscore before the alias name depends on the target platform. Win32 requires one.

Jonas

Coco Pascal
to Jonas Maebe
Jonas Maebe wrote 43 lines
On 31 May 2009, at 15:28, Coco Pascal wrote: > Marco van de Voort schreef: >> In our previous episode, Coco Pascal said: >> >>> I have a library with udf routines using the cdecl calling >>> convention, required by Firebird. This seems to work well on win32. >> >> How exactly? >> > > ? > > function Y_Odd(const AValue: Int64): LongInt; cdecl; export; > begin > if Odd(AValue) then > Result := -1 > else > Result := 0; > end; {Y_Odd} > > exports > > Y_Odd; > > This works fine with Firebird. If I declare the stdcall calling > convention Firebird can't find its entrypoint. cdecl automatically enables C-compiler-compatible name mangling for exported procedures. stdcall doesn't. So it's normal that Firebird does not find the entrypoint when using stdcall, as it does not support FPC-style name mangling. There is no way to get C name mangling without the calling convention, so you have to manually declare an alias in that case. E.g., > function Y_Odd(const AValue: Int64): LongInt; cdecl; alias: '_Y_Odd'; > export; Whether or not you need an extra underscore before the alias name depends on the target platform. Win32 requires one.
I tried
function Y_Odd(const AValue: Int64): LongInt; cdecl; alias: '_Y_Odd';
export;
and
function Y_Odd(const AValue: Int64): LongInt; cdecl; alias: '__Y_Odd';
export;
but still I get the message entrypoint of 'Y_Odd' could not be found in
'libyfbudf.dll'
Jonas Maebe
to Coco Pascal
Coco Pascal wrote 8 lines
I tried function Y_Odd(const AValue: Int64): LongInt; cdecl; alias: '_Y_Odd'; export; and function Y_Odd(const AValue: Int64): LongInt; cdecl; alias: '__Y_Odd'; export; but still I get the message entrypoint of 'Y_Odd' could not be found in 'libyfbudf.dll'

Then you may want to use some tool to look at the name of the entry point in the dll for the cdecl case, and compare it to the stdcall case. Since I don't use Windows, I cannot help you with this.

Jonas

Coco Pascal
to Jonas Maebe
Jonas Maebe wrote 17 lines
On 31 May 2009, at 20:05, Coco Pascal wrote: > I tried > function Y_Odd(const AValue: Int64): LongInt; cdecl; alias: '_Y_Odd'; > export; > and > function Y_Odd(const AValue: Int64): LongInt; cdecl; alias: > '__Y_Odd'; export; > but still I get the message entrypoint of 'Y_Odd' could not be found > in 'libyfbudf.dll' Then you may want to use some tool to look at the name of the entry point in the dll for the cdecl case, and compare it to the stdcall case. Since I don't use Windows, I cannot help you with this.

Thanks for the tip! The name in the dll is _Y_Odd indeed. Is it not the function header in the dll that must extended with alias: '_Y_Odd'. The function declaration in the app should be: function _Y_Odd(const AValue: Int64): LongInt; cdecl; external 'libyfbudf.dll';