Discussion:
[Mono-list] Mono/.NET delegate incompatibility
J. Perkins
2002-12-18 20:24:22 UTC
Permalink
I am using a delegate to pass a function pointer into a unmanaged DLL.
Under Linux/Mono everything works fine. Under Windows/.NET, my callback
function signature must look like this:

void (__stdcall *func)(int);

But Windows/Mono seems to want:

void (*func)(int);

Changing the signature will cause the other CLR to corrupt the stack.

Jason
379
Tum
2002-12-18 23:43:57 UTC
Permalink
I guess the default calling convention in mono is cdecl. According to
MSDN, the default calling convention for dllimport should be stdcall
(which IMHO really only makes sense on windows).

You could try setting the CallingConvention property on the DllImport to
cdecl.

e.g.

[DllImport("mydll.dll", CallingConvention=CallingConvention.Cdecl)]
public static extern void myfunc(int x);

^Tum
-----Original Message-----
On
Behalf Of J. Perkins
Sent: Thursday, 19 December 2002 9:24 a.m.
To: Mono-L
Subject: [Mono-list] Mono/.NET delegate incompatibility
I am using a delegate to pass a function pointer into a unmanaged DLL.
Under Linux/Mono everything works fine. Under Windows/.NET, my
callback
void (__stdcall *func)(int);
void (*func)(int);
Changing the signature will cause the other CLR to corrupt the stack.
Jason
379
_______________________________________________
http://lists.ximian.com/mailman/listinfo/mono-list
J. Perkins
2002-12-19 13:39:17 UTC
Permalink
This is a good workaround. Thanks!

Jason
379
Post by Tum
I guess the default calling convention in mono is cdecl. According to
MSDN, the default calling convention for dllimport should be stdcall
(which IMHO really only makes sense on windows).
You could try setting the CallingConvention property on the DllImport to
cdecl.
e.g.
[DllImport("mydll.dll", CallingConvention=CallingConvention.Cdecl)]
public static extern void myfunc(int x);
J. Perkins
2002-12-19 19:42:12 UTC
Permalink
Hang on a minute, I answered this too soon. I'm not talking about
calling a DLL function. [DllImport] works just fine on both Windows and
Linux. I am talking about a callback function, from unmanaged -> managed
code. That is, a C# delegate passed to and called from unmanaged code
via a function pointer. Here's a usenet thread on the subject:

http://makeashorterlink.com/?C417214D2

The problem described in this thread is reversed for Mono: the callback
must use the cdecl convention. Because of this, there is no way to write
a C function that can call a delegate under both .NET and Mono. If I do
this:

int SomeCFunction(int (__stdcall *callback)(int, int, int))
{ return callback(1,2,3); }

...it will corrupt the stack when run under Mono on Windows. If I use
cdecl instead:

int SomeCFunction(int (*callback)(int, int, int))
{ return callback(1,2,3); }

...it will corrupt the stack when run under .NET. Maybe I'm missing
something (quite possible), but it appears that Mono must use __stdcall
for delegates on Windows.

I'll give you guys a chance to sanity check my rambling. If it holds up
I will file a bug.

Jason
379
Post by Tum
I guess the default calling convention in mono is cdecl. According to
MSDN, the default calling convention for dllimport should be stdcall
(which IMHO really only makes sense on windows).
You could try setting the CallingConvention property on the DllImport to
cdecl.
dietmar
2002-12-20 08:49:48 UTC
Permalink
Please file a bug.

- Dietmar
Post by J. Perkins
Hang on a minute, I answered this too soon. I'm not talking about
calling a DLL function. [DllImport] works just fine on both Windows and
Linux. I am talking about a callback function, from unmanaged -> managed
code. That is, a C# delegate passed to and called from unmanaged code
http://makeashorterlink.com/?C417214D2
The problem described in this thread is reversed for Mono: the
callback
must use the cdecl convention. Because of this, there is no way to write
a C function that can call a delegate under both .NET and Mono. If I do
int SomeCFunction(int (__stdcall *callback)(int, int, int))
{ return callback(1,2,3); }
...it will corrupt the stack when run under Mono on Windows. If I use
int SomeCFunction(int (*callback)(int, int, int))
{ return callback(1,2,3); }
...it will corrupt the stack when run under .NET. Maybe I'm missing
something (quite possible), but it appears that Mono must use
__stdcall
for delegates on Windows.
I'll give you guys a chance to sanity check my rambling. If it holds up
I will file a bug.
Jason
379
Post by Tum
I guess the default calling convention in mono is cdecl.
According to
Post by Tum
MSDN, the default calling convention for dllimport should be
stdcall
Post by Tum
(which IMHO really only makes sense on windows).
You could try setting the CallingConvention property on the
DllImport to
Post by Tum
cdecl.
_______________________________________________
http://lists.ximian.com/mailman/listinfo/mono-list
Miguel de Icaza
2002-12-19 00:41:30 UTC
Permalink
Hello,
Post by J. Perkins
I am using a delegate to pass a function pointer into a unmanaged DLL.
Under Linux/Mono everything works fine. Under Windows/.NET, my callback
void (__stdcall *func)(int);
void (*func)(int);
__stdcall is a Microsoft-C feature, so it is really a feature of your
compiler. There are some macros around that you can use to make your C
code portable (not really Mono's domain), like STDCALL that get defined
to nothing on Unix.

Miguel
Fergus Henderson
2002-12-19 03:18:35 UTC
Permalink
Post by Miguel de Icaza
Hello,
Post by J. Perkins
I am using a delegate to pass a function pointer into a unmanaged DLL.
Under Linux/Mono everything works fine. Under Windows/.NET, my callback
void (__stdcall *func)(int);
void (*func)(int);
__stdcall is a Microsoft-C feature, so it is really a feature of your
compiler.
It's also a feature also of the Windows ABI.

Note that support for __stdcall has just recently been added to GCC
(the main CVS branch -- it should be included in GCC 3.4, I think).
--
Fergus Henderson <***@cs.mu.oz.au> | "I have always known that the pursuit
The University of Melbourne | of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh> | -- the last words of T. S. Garp.
Jonathan Pryor
2002-12-19 12:43:55 UTC
Permalink
`__stdcall' (the keyword) was just added for GCC 3.4, or "stdcall" stack
ordering was just added?

It can't be the latter. I know I've used "stdcall" functions from GCC
since (at least!) 2.95, probably earlier. It's needed to call any Win32
API function.

Granted, it was `__attribute__((stdcall))', not `__stdcall', so that
might be the difference.

Either way, if you need to compile a function using the `stdcall'
calling convention under GCC, this should work:

#ifndef STDCALL
#define STDCALL __attribute__((stdcall))
#endif

void (STDCALL *func)(int);

- Jon
Post by Fergus Henderson
Post by Miguel de Icaza
Hello,
Post by J. Perkins
I am using a delegate to pass a function pointer into a unmanaged DLL.
Under Linux/Mono everything works fine. Under Windows/.NET, my callback
void (__stdcall *func)(int);
void (*func)(int);
__stdcall is a Microsoft-C feature, so it is really a feature of your
compiler.
It's also a feature also of the Windows ABI.
Note that support for __stdcall has just recently been added to GCC
(the main CVS branch -- it should be included in GCC 3.4, I think).
J. Perkins
2002-12-19 13:38:10 UTC
Permalink
Okay, I can change my code no problem, but won't this prevent Mono from
calling functions in the windows system DLLs? Those must all use
__stdcall. I am totally swamped right now (trying to get a release out
before the holidays) but if I get a chance I will try to access some
win32 api functions and see what happens.

Jason
379
Post by Miguel de Icaza
__stdcall is a Microsoft-C feature, so it is really a feature of your
compiler. There are some macros around that you can use to make your C
code portable (not really Mono's domain), like STDCALL that get defined
to nothing on Unix.
Piers Haken
2002-12-19 22:25:23 UTC
Permalink
you're right, in order to remain compatible, mono should use stdcall
convention by default on win32. (existing code, etc...)

piers.

-----Original Message-----
From: J. Perkins [mailto:***@379.com]
Sent: Thursday, December 19, 2002 11:42 AM
To: J. Perkins
Cc: 'Mono-L'
Subject: RE: [Mono-list] Mono/.NET delegate incompatibility


Hang on a minute, I answered this too soon. I'm not talking about
calling a DLL function. [DllImport] works just fine on both Windows and
Linux. I am talking about a callback function, from unmanaged -> managed
code. That is, a C# delegate passed to and called from unmanaged code
via a function pointer. Here's a usenet thread on the subject:

http://makeashorterlink.com/?C417214D2

The problem described in this thread is reversed for Mono: the callback
must use the cdecl convention. Because of this, there is no way to write
a C function that can call a delegate under both .NET and Mono. If I do
this:

int SomeCFunction(int (__stdcall *callback)(int, int, int))
{ return callback(1,2,3); }

...it will corrupt the stack when run under Mono on Windows. If I use
cdecl instead:

int SomeCFunction(int (*callback)(int, int, int))
{ return callback(1,2,3); }

...it will corrupt the stack when run under .NET. Maybe I'm missing
something (quite possible), but it appears that Mono must use __stdcall
for delegates on Windows.

I'll give you guys a chance to sanity check my rambling. If it holds up
I will file a bug.

Jason
379
Post by Tum
I guess the default calling convention in mono is cdecl. According
to
Post by Tum
MSDN, the default calling convention for dllimport should be stdcall
(which IMHO really only makes sense on windows).
You could try setting the CallingConvention property on the
DllImport to
Post by Tum
cdecl.
_______________________________________________
Mono-list maillist - Mono-***@ximian.com
http://lists.ximian.com/mailman/listinfo/mono-list
Loading...