Trouble with DLL stdcall and no name decoration

General FreeBASIC programming questions.
D.J.Peters
Posts: 7341
Joined: May 28, 2005 3:28

Trouble with DLL stdcall and no name decoration

Postby D.J.Peters » Mar 12, 2018 14:57

I try to write a 32-bit DLL plugin for a game with FreeBASIC
but if the plugin are loaded the game crashed.

It must be __stdcall without name decoration.

plugin_bas.dll create a beep if loaded than the game crashs.

plugin_c.dll create a beep if loaded and while it runs without any problem.

Any idea why C++ works but not the FreeBASIC build ?

Joshy

file: plugin_bas.bas

Code: Select all

Extern "Windows-MS" ' <--- using stdcall without @XX name decoration

sub Start (byval pForm as any ptr) export
  beep()
end sub

sub Finalize ()  export
  beep()
  beep()
end sub

sub AccessVariable (byval Index as ushort, byval Value as single ptr, byval blnWrite as ubyte ptr) export
end sub

sub AccessTrigger (byval Index as ushort, byval blnActive as ubyte ptr) export
end sub

end extern
the same in C++ works
file: plugin_c.h

Code: Select all

#ifndef __PLUGIN_H__
#define __PLUGIN_H__

#ifdef WIN32
  #include <windows.h>
#else
  #error Target must be WIN32 !
#endif

extern "C"  void __stdcall Start(void* form);
extern "C"  void __stdcall AccessVariable(unsigned short varindex, float* value, bool* write);
extern "C"  void __stdcall AccessTrigger(unsigned short triggerindex, bool* active);
extern "C"  void __stdcall Finalize();
#endif // __PLUGIN_H__

file: plugin_c.cpp

Code: Select all

#include "plugin_c.h"

void  Start(void* form) {
  Beep(440,500);
}
void  AccessVariable(unsigned short varindex, float* value, bool* write) {
  Beep(440,10);
}
void  AccessTrigger(unsigned short triggerindex, bool* active) {
}
void  Finalize() {
  Beep(220,500);
}
D.J.Peters
Posts: 7341
Joined: May 28, 2005 3:28

Re: Trouble with DLL stdcall and no name decoration

Postby D.J.Peters » Mar 12, 2018 15:28

Of course the game it self isn't compiled with debug infos -g
but if I run the game with gdb and the BASIC plugin crashes stacktrace prints out "corrupt stack frame"

Joshy
D.J.Peters
Posts: 7341
Joined: May 28, 2005 3:28

Re: Trouble with DLL stdcall and no name decoration

Postby D.J.Peters » Mar 12, 2018 15:47

Locks like the beep command works from sub Start but than the game crashed while loading textures.
Can it be that a FreeBASIC DLL change the current PATH or any environment var of the calling main process ?

Joshy
MrSwiss
Posts: 2387
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Trouble with DLL stdcall and no name decoration

Postby MrSwiss » Mar 12, 2018 15:54

"corrupt stack frame"
I'd check 2 things (second because, I don't know the size(in bytes) of bool in C).
1) the UByte Ptr (correct ? or rather Boolean Ptr ?)
2) is the size of the C bool correct for byte/boolean in FB ?
If a C bool is, e.g. sizeof(int/uint), you'll have to use: Long/ULong Ptr in FB.
D.J.Peters
Posts: 7341
Joined: May 28, 2005 3:28

Re: Trouble with DLL stdcall and no name decoration

Postby D.J.Peters » Mar 12, 2018 16:25

A pointer is a pointer and I don't touch it
so it plays no rule dose it point to boolean, bool=byte, int or long you know ?
on stack a pointer is 4 byte on 32-bit.

Joshy
MrSwiss
Posts: 2387
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Trouble with DLL stdcall and no name decoration

Postby MrSwiss » Mar 12, 2018 16:34

Well, I was actually referring to: size of allocated memory (to Ptr),
not the Ptr size, itself.
D.J.Peters
Posts: 7341
Joined: May 28, 2005 3:28

Re: Trouble with DLL stdcall and no name decoration

Postby D.J.Peters » Mar 14, 2018 1:37

Why FB access (read) the stack and create a temporary var in the stack space if the sub's are empty ?

Joshy

Code: Select all

Extern "Windows-MS" ' stdcall no @# decoration
sub AccessVariable (byval Index as ushort, byval Value as single ptr, byval blnWrite as ubyte ptr) export
end sub
sub AccessTrigger (byval Index as ushort, byval blnActive as ubyte ptr) export
end sub
end extern

Code: Select all

L6:
   .globl   _AccessVariable
   .def   _AccessVariable;   .scl   2;   .type   32;   .endef
_AccessVariable:
   push   ebp
   mov   ebp, esp
   sub   esp, 4
   mov   eax, DWORD PTR [ebp+8]
   mov   WORD PTR [ebp-4], ax
   nop
   leave
   ret   12
L8:
L9:
   .globl   _AccessTrigger
   .def   _AccessTrigger;   .scl   2;   .type   32;   .endef
_AccessTrigger:
   push   ebp
   mov   ebp, esp
   sub   esp, 4
   mov   eax, DWORD PTR [ebp+8]
   mov   WORD PTR [ebp-4], ax
   nop
   leave
   ret   8

The C++ DLL does not access the stack and works

Code: Select all

   .p2align 4,,15
   .globl   AccessVariable
AccessVariable:
   ret   $12
   .p2align 4,,15
   .globl   AccessTrigger
   .def   AccessTrigger;   .scl   2;   .type   32;   .endef
AccessTrigger:
   ret   $8
SARG
Posts: 826
Joined: May 27, 2005 7:15
Location: FRANCE

Re: Trouble with DLL stdcall and no name decoration

Postby SARG » Mar 14, 2018 10:24

Hi,

When accesstrigger (same with accessvariable) is called Index is put on stack as DWORD then in the sub it's put in another location as a WORD....
By the way with GAS only prologue and epilogue, no code added.

Tested in a simplier way.

Code: Select all

sub AccessTrigger (ByVal Index as UShort)
Print index
end Sub
AccessTrigger(10)

Code: Select all

   .globl   _AccessTrigger
   .def   _AccessTrigger;   .scl   2;   .type   32;   .endef
_AccessTrigger:
   push   ebp
   mov   ebp, esp
   sub   esp, 40
   mov   eax, DWORD PTR [ebp+8]
   mov   WORD PTR [ebp-12], ax    <---- stored as a WORD
L5:
   mov   eax, DWORD PTR [ebp-12]
   and   eax, 65535
   mov   DWORD PTR [esp+8], 1
   mov   DWORD PTR [esp+4], eax
   mov   DWORD PTR [esp], 0
   call   _fb_PrintUShort@12
   sub   esp, 12
   leave
   ret   4

Code: Select all

   mov   DWORD PTR [esp], 10  <----- stored as DWORD
   call   _AccessTrigger
   sub   esp, 4
D.J.Peters
Posts: 7341
Joined: May 28, 2005 3:28

Re: Trouble with DLL stdcall and no name decoration

Postby D.J.Peters » Mar 14, 2018 15:16

@SARG good find you are right -gen gcc creates a temporary var and read the index from stack and -gen gas creates only the prolog and epilog of the sub.

The problem are fb calls inside the created dll _main and than from _main are __main called also.
Looks like __main setup a kind of environment for the dll.

if the gane calls the C dll Start() sub I get the beep
and I see this 3 massages on the game loader dialog
"loading environment traffic"
"loading textures"
"loading AI"
then the game starts and every render frame AccessVariable, AccessTrtigger are called

if the gane calls the FB dll Start() sub I get the beep
and I see only 2 massages on the game loader dialog
"loading environment traffic"
"loading textures"
then the game crashes with an entry in a log file "can't read texture".

I don't know why the game can't find or read the texture after the FB created dll are loaded.

May be the FB created dll changes the path of the caller or overwrites a part of the environment vars I don't know :-(

Joshy
marcov
Posts: 2486
Joined: Jun 16, 2005 9:45
Location: Eindhoven, NL
Contact:

Re: Trouble with DLL stdcall and no name decoration

Postby marcov » Mar 14, 2018 16:27

If code like _start ends up in dllmain (or called via dllmain), there are limitations what is allowed there, see https://blogs.msdn.microsoft.com/oldnew ... 0/?p=40873
SARG
Posts: 826
Joined: May 27, 2005 7:15
Location: FRANCE

Re: Trouble with DLL stdcall and no name decoration

Postby SARG » Mar 14, 2018 21:05

Have you tried other calls of subs without parameters ? subs contained in the dll..... instaed of accesstrigger

If possible post reduced code giving the error ?

I don't understand what you wrote :
"The problem are fb calls inside the created dll _main and than from _main are __main called also.
Looks like __main setup a kind of environment for the dll."
D.J.Peters
Posts: 7341
Joined: May 28, 2005 3:28

Re: Trouble with DLL stdcall and no name decoration

Postby D.J.Peters » Mar 15, 2018 1:27

@SARG the game OMSI a bus-driver simulation and call's the sub's inside a plugin dll.

So if the subs are empty there isn't any reason while the FB build dll crashes and the C/C++ dll works fine here.

If you compile any stuff with FreeBASIC you can view the created assembler list with the command line option -RR
fbc -RR stuff.bas

in case of a DLL
fbc -RR -dll stuff.bas

you get the file stuff.asm with calls to _main and __main also
(I don't know what this calls do inside the DLL)

The FB created dll is ~18KB the C/C++ dll only ~10K

bla bla bla :-)

I don't have time for this kind of trouble so I will write my OMSI pluigin in C/C++ know.

How ever thank you all for you help and support.

Joshy

Return to “General”

Who is online

Users browsing this forum: No registered users and 5 guests