Topaz Filer: if you use e-mail for business, we can save you money and decrease your risk.
Callback function using C calling convention.
Messages   Related Types
This message was discovered on microsoft.public.dotnet.framework.interop.


Nicolas Faucher
GOOD ANSWER
Hi,

I hope you can help me on this. I'm calling a unmanaged C DLL from my C#
application. I'm able to call the function correctly. This function take a
pointer to a fonction (like callback functions in Win32). I have declared a
delegate in my code and pass it to the unmanaged C function. My callback is
called some times and after that I'm receiving a NullReference exception. I
searched what's the problem and find that the callback function must use C
calling convention. I searched the documentation to find if there is a way
to specify the calling convention of a delegate (which I suppose is stdcall
by default) but without success. I really think it's the cause of the
exception thrown.

So, how to change the calling convention of a delegate when used in
unmanaged code? If not, what I can do for this? I know I can use Managed
C++ to wrap this DLL but I really appreciate to have a totally C# solution.

Thanks

Reply to this message...
Vote that this is a GOOD answer... (5 votes from other users already)
 
 
    
Eliyahu \(Vyacheslav\) Biktagirov
GOOD ANSWER
You can specify CallingConvention.CDecl for your callback
delegate
Reply to this message...
Vote that this is a GOOD answer... (6 votes from other users already)
 
 
    
Nicolas Faucher
GOOD ANSWER
Ok, but how? Using a attribute, which one?

"Eliyahu (Vyacheslav) Biktagirov" <Click here to reveal e-mail address> wrote in message
news:06ee01c1e912$2d8cf460$19ef2ecf@tkmsftngxa01...
[Original message clipped]

Reply to this message...
Vote that this is a GOOD answer... (4 votes from other users already)
 
 
    
Eliyahu \(Vyacheslav\) Biktagirov
GOOD ANSWER
Oh, you are right.

Unfortunately, we are not able to specify the Calling
Convention for
Delegates and C# Class Methods.

If your legacy DLL is used by a number of applications and
cannot be
modified, I suggest you implement a Wrapper DLL with
appropriate Calling
Convention.

Hope this helps!

Reply to this message...
Vote that this is a GOOD answer... (3 votes from other users already)
 
 
    
Jan Kotas [MS]
GOOD ANSWER
The C# does not allow you to specify the calling convention of the callback.
It is just one of the C# limitations. IL, managed C++ and the runtime itself
supports the cdecl calling convention for delegates through
modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl) on the
internal Invoke method of the delegate. Run ildasm on a small example in
managed C++ if you want to know the exact syntax.

You can use the following trick if you want to write all your code in C#:

- Create a private placeholder attribute to mark your C# delegates that
needs cdecl calling convention
- Compile your C# to an assembly
- Use the ildasm dissasembler to store the resulting assembly as raw IL.
- Modify the IL to change the calling convention on the delegates marked
with the placeholder attribute
- Use ilasm to compile the modified raw IL again.

The whole process can be automated. You can find example of how to automate
the process in the Shared Source CLI samples. The Shared Source CLI (aka
Rotor) can be downloaded from http://msdn.microsoft.com/net/sscli . The
following files have the interesting stuff about the cdecl calling
convention for delegates:

sscli\docs\techinfo\native_managed_interop.html
sscli\samples\pigui\tk\makefile.inc
sscli\samples\pigui\tk\callconvattribute.cs
sscli\samples\pigui\tk\callconvhack.pl
sscli\samples\pigui\tk\tclnative.cs

You will need perl (e.g. from http://www.activestate.com) if you want to use
the script as is. It should be fairly easy to rewrite callconvhack.pl in any
other language though.

Here are the code snipets if you are on a slow link and don't have time to
download 10+MB Rotor tarball at the moment:

makefile.inc:
--------------------
....
csc /out:myassembly.dll callconvattribute.cs mydelegate.cs ...
ildasm myassembly.dll /out:myassembly.il1
perl callconvhack.pl <myassembly.il1 >myassembly.il2
ilasm /DLL /QUIET myassembly.il2
....
--------------------

mydelegate.cs:
--------------------
....
[CallConvCdecl] internal delegate int MyDelegate(int param);
....
--------------------

callconvattribute.cs:
--------------------
// cdecl calling convetion for delegates - the signature of delegates
// marked with this attribute is changed to cdecl in callconvhack.pl

using System;

[Serializable, AttributeUsage (AttributeTargets.Delegate)]
public sealed class CallConvCdeclAttribute : Attribute
{
public CallConvCdeclAttribute()
{
}
}
--------------------

callconvhack.pl:
--------------------
# change references to CallConvAttribute into
modopt([mscorlib]System.Runtime.CompilerServices.*)

while(<>) {
if (m/\.class .* CallConv.*Attribute/) {
$incallconvattributeimpl=1;
next;
}
if(m/\/\/ end of class CallConv.*Attribute/) {
$incallconvattributeimpl=0;
next;
}

if(m/\.custom instance void CallConv(.*)Attribute/) {
$pendingcallconv = $1;
next;
}

if ($pendingcallconv) {
if(m/.*Invoke\(.*/) {
print
"modopt([mscorlib]System.Runtime.CompilerServices.CallConv" .
$pendingcallconv . ")\n";
$pendingcallconv = "";
}
}

print unless $incallconvattributeimpl;
}
--------------------

This posting is provided "AS IS" with no warranties, and confers no rights.

"Nicolas Faucher" <Click here to reveal e-mail address> wrote in message
news:uwmLrrN6BHA.2360@tkmsftngp04...
[Original message clipped]

Reply to this message...
Vote that this is a GOOD answer... (5 votes from other users already)
 
 
    
Eric Gunnerson [MS]
GOOD ANSWER
If you create a delegate and pass it off to the unmanaged code and it works
a while a then bombs, my guess is that you aren't keeping a reference to the
delegate around, and the GC is coming along and cleaning it up for you.

You can test this by calling GC.Collect() right after you do the delegate.
If you do that, the first call should fail.

You can fix this by keeping a reference to the delegate where the GC can
find it (ie as an instance variable).

--
Visit the C# product team at http://www.gotdotnet.com/team/csharp

This posting is provided "AS IS" with no warranties, and confers no rights.

"Nicolas Faucher" <Click here to reveal e-mail address> wrote in message
news:uwmLrrN6BHA.2360@tkmsftngp04...
[Original message clipped]

Reply to this message...
Vote that this is a GOOD answer... (4 votes from other users already)
 
 
 
System.AttributeTargets
System.GC
System.Runtime.CompilerServices.CallConvCdecl
System.Runtime.InteropServices.CallingConvention




Ad
BootFX
Reliable and powerful .NET application framework.
Recession Busting Bespoke Software
Get through the recession by investing in bespoke software to decrease costs and create commercial opportunities.
Other DN247 Network Sites
.NET 247
SQL Server Wins
Old Skool Developer
 
Copyright © AMX Software Ltd 2008-2009. Portions copyright © Matthew Baxter-Reynolds 2001-2009. All rights reserved.
Contact Us - Terms of Use - Privacy Policy - .NET 247 is a member of the DN247 Network - 4.0.30129.1734