Mail Archives: cygwin/1998/06/06/07:27:21
Hi,
I have some questions and observations about using a dll made by using
Cygnus with MS VC++.
1.
First, I never manage to use the functions malloc, free, realloc in my dll.
I had to use pointer instead, and Initialized them in my VC progam with
functions malloc, realloc and free of VC.
This prevent me from using system functions which use malloc, realloc or
free, like fdopen, sscanf...
I don't know if this is a normal behaviour or not.
2.
The struct FILE are totally different, so you can't call a function using
you VC FILE* or VC std[in/out].
3.
Moreover, Cygnus doesn't seem to call functions the same way as VC does :
For instance, with the declarations :
typedef struct
{
int n1;
int n2;
int n3;
int n4;
} quad;
quad Associe(int n1, int n2, int n3, int n4) // function with complex result
{
quad pRes;
pRes.n1=n1;
pRes.n2=n2;
pRes.n3=n3;
pRes.n4=n4;
return(pRes);
}
int nRendPreums(int,int); // function with simple argument
In my program, I get :
for the simple function :
-------
with Cygnus
46 nI=nRendPreums(1,2);
0x4011ef <main+35>: pushl $0x2
0x4011f1 <main+37>: pushl $0x1
0x4011f3 <main+39>: call 0x40159c <nRendPreums>
0x4011f8 <main+44>: addl $0x8,%esp
0x4011fb <main+47>: movl %eax,%eax
0x4011fd <main+49>: movl %eax,0xfffffff4(%ebp)
--
with VC++
74: nTest=nRendPreums(1,2);
004012A4 push 2
004012A6 push 1
004012A8 call dword ptr [_nRendPreums(0x00416fdc)]
004012AE add esp,8
004012B1 mov dword ptr [nTest],eax
-------
and for the complex function :
-------
with Cygnus :
52 MonQuad=Associe(1,2,3,4);
0x4011f7 <main+19>: leal 0xfffffff0(%ebp),%eax
0x4011fa <main+22>: pushl $0x4
0x4011fc <main+24>: pushl $0x3
0x4011fe <main+26>: pushl $0x2
0x401200 <main+28>: pushl $0x1
0x401202 <main+30>: pushl %eax // the address of MonQuad is
stored
on the stack before calling
Associe
0x401203 <main+31>: call 0x401040 <Associe>
0x401208 <main+36>: addl $0x10,%esp
--
with VC++
78: MonQuad=Associe(1,2,3,4);
004012A9 push 4
004012AB push 3
004012AD push 2
004012AF push 1
004012B1 lea ecx,dword ptr [ebp-54h]
004012B4 push ecx
004012B5 call @ILT+25(?Associe@@YA?AUquad@@HHHH AT Z)(0x00401019) //
call to Associe
004012BA add esp,14h
004012BD mov edx,dword ptr [eax] // the 1st result value is
stored in edx
004012BF mov dword ptr [ebp-44h],edx // then put on the stack
004012C2 mov ecx,dword ptr [eax+4]
004012C5 mov dword ptr [ebp-40h],ecx // idem for 2nd result with
ecx
004012C8 mov edx,dword ptr [eax+8]
004012CB mov dword ptr [ebp-3Ch],edx // idem for 3rd, edx
004012CE mov eax,dword ptr [eax+0Ch]
004012D1 mov dword ptr [ebp-38h],eax // and the 4th, eax
004012D4 mov ecx,dword ptr [ebp-44h]
004012D7 mov dword ptr [MonQuad],ecx // MonQuad.n1 is set
004012DA mov edx,dword ptr [ebp-40h]
004012DD mov dword ptr [ebp-1Ch],edx // MonQuad.n2 too
004012E0 mov eax,dword ptr [ebp-3Ch]
004012E3 mov dword ptr [ebp-18h],eax // MonQuad.n3
004012E6 mov ecx,dword ptr [ebp-38h]
004012E9 mov dword ptr [ebp-14h],ecx // MonQuad.n4
---------
Here, functions are _cdecl, but the result is the same with __stdcall
functions (exect for the "add xxx, esp")
So, for function whose result is not longer than 32 bits (the length of a
register), wa can see than the call is done the same way :
- The arguments are put on the stack from right to left
- The result is store in eax
However, if the result is larger than 32 bits, Cygnus and VC++ don't behave
the same way :
- after the arguments, Cygnus put on the stack the address
of the object modified by the function.
- VC doesn't. Instead, the address of the result is stored in eax.
After the call, the result is store in the object.
This means that a VC function can't call a Cygnus function whose result is
larger than a register (larger than an int or a pointer).
Moreover, this test was made in debug mode for both sides. I don't know what
the optimisations could change in the way arguments are stored on the stack.
As I'm not a crack about C, compilers and Windows, I still ahve a few
questions :
- Is there any standard for calling a function in a Windows'dll ?
- Is there another keyword which could make one of the compiler behave
like the other ?
Today, it seems to me that I must have in my dll functions that don't use
malloc directly or inderectly but import such functions (for instance, I
import within a dll malloc, realloc free and sscanf, with other names of
course), and that returns only pointer on struct and not struct themselves.
Of course, you can also rewrite a function in VC++ with an _asm section
calling your function the good way, it seems to work fine.
Well, that's all, I hope that someone could say me if I really missed
something, for the memory functions and for functions call, and then explain
how to make VC and Cygnus work one with the other simply.
Bye
--------------------------------------------------------------
Jerome GRANDJEAN SUPELEC
Email : jgrandje AT supelec-rennes DOT fr 51 bis Bd de Sevigne
Tel : 02.99.38.20.77 35700 RENNES
TAM TAM : 06.01.43.57.60 FRANCE
-
For help on using this list (especially unsubscribing), send a message to
"gnu-win32-request AT cygnus DOT com" with one line of text: "help".
- Raw text -