I have written a VC++ dll. The declaration for one of the methods in the dll is as follows:
extern "C" _declspec(dllexport)
void startIt(int number)
{
capture = cvCaptureFromCAM(number);
}
I use this dll in a C# code using P/Invoke. I make the declaration as:
[DllImport("Tracking.dll", EntryPoint = "startIt")]
public extern static void startIt(int number);
and I call the function in the code as:
startIt(0);
Now, when this line is encountered, the compiler is throwing me this error:
A call to PInvoke function 'UsingTracking!UsingTracking.Form1::startIt' has
unbalanced the stack. This is likely because the managed PInvoke signature does
not match the unmanaged target signature. Check that the calling convention
and parameters of the PInvoke signature match the target unmanaged signature.
I cannot understand why is it throwing this error as the signature in both managed and unmanaged code are the same. Moreover, in my another machine, the same code is running perfectly in visual studio. So, this makes me think that the error thrown is mis leading.
Please help.
Thanks
When you p/invoke an external function, the calling convention used defaults to __stdcall. Since your function uses the __cdecl convention, you need to declare it as such:
[DllImport("Tracking.dll", EntryPoint = "startIt",
CallingConvention = CallingConvention.Cdecl)]
public extern static void startIt(int number);
Could you be missing CallingConvention=CallingConvention.Cdecl in your DllImport attribute?
Constantin and Frederic Hamidi have answered this question correctly as to how to fix this problem. This can help avoid an eventual stack overflow. I have bitten by this several times myself. What is really at play here is that .NET 4 has enabled a managed debugging assistant for debug (not release) builds on 32 bit x86 machines (not 64 bit ) that checks for an incorrectly specified p/invoke call. This MSDN article details this : http://msdn.microsoft.com/en-us/library/0htdy0k3.aspx. Stephen Cleary deserves the credit for identifying this on this post: pinvokestackimbalance -- how can I fix this or turn it off?
Related
A third-party app I have can call extension DLLs if they have C-compliant interfaces as described below.
I would like the third-party app to call my C# DLL, since I would rather write in C# than C. (Maybe my other choice would be to write a C DLL wrapper to call my C# DLL, which is an extra step that I might not get right).
I've searched the net and SO but haven't found (or recognized) a good match to my question.
The best suggestion seemed to be this special marshalling declarations in the C# code here: Calling a C# DLL from C; linking problems
Is it possible to write a C# DLL that has a C-compliant interface like the one below? If so, could someone tell me what I have to do or point me to some documentation?
The third-party app documentation says, "The DLL function must be a PASCAL function that takes a single LPCSTR (long pointer to a constant string) argument. C or C++ DLL functions called must have prototypes equivalent to:
extern "C" __declspec(dllexport) void __stdcall fn(LPCTSTR szParam );
Take a look at this article: https://www.codeproject.com/Articles/12512/Using-the-CDECL-calling-convention-in-C-changing
It discusses a different problem (opposite to yours) but also explains the linkage of C# functions - by default C# uses __stdcall (and it cannot be overridden). This means your third party app should be able to call the C# function as it stands. Have you tried it? Did you get any errors?
I am trying to calling a game functions with code injection. after some try I find a dll that did what I want.
so i saw the dll with ILSpy but cannot understand the code.
class <Module>
{
[SecurityCritical, SuppressUnmanagedCodeSecurity]
[DllImport("", CallingConvention = CallingConvention.ThisCall, SetLastError = true)]
[MethodImpl(MethodImplOptions.Unmanaged)]
internal unsafe static extern float* GetHealth(AttackableUnit*);
}
--------------------------
namespace Native
{
[NativeCppClass]
[StructLayout(LayoutKind.Sequential, Size = 1)]
internal struct AttackableUnit
{
}
}
---------------------
public unsafe float MaxHealth
{
get
{
Native.AttackableUnit* ptr = (Native.AttackableUnit*)base.GetPtr();
if (ptr != null)
{
return *<Module>.Native.AttackableUnit.GetMaxHealth(ptr);
}
return 0f;
}
}
Seems the dll inject c# code to the target app with a c++ dll and bootstrap .net in target.
And now I cannot understand what is the meaning of
[DllImport("", CallingConvention = CallingConvention.ThisCall,
SetLastError = true)]
Why is the file path empty?
How does the dll manage class and function call? I mean what technique the programmer use?
EDIT :
The name of library that I am trying to understand is Elobuddy perhaps helps.
Trying not to kick in a wide-open door, the C# language was not involved in generating this assembly. You are seeing the output of a C++/CLI project. A mixed-mode assembly, it contains both MSIL and native code. You'd generate a similar assembly with File > New > Project > Visual C++ > CLR > Class Library.
The author probably favored it to solve the CLR injection problem. It is not possible to inject a pure managed DLL into another process, the CLR has to first be loaded and initialized before it can execute any managed code. A chicken-and-egg problem that requires reverse-pinvoke (native code calling managed code) the opposite of what [DllImport] does. C++/CLI makes that very easy, I describe the technique in this answer. The Unmanaged Exports utility is popular (google DllExport), an assembly rewriter that uses the same technique that C++/CLI uses.
But the author also wanted to use native C++ code to implement the game hack. He is using a pure native DLL, it contains the GetHealth() function and AttackableUnit class definition. This DLL is implicitly loaded by the OS loader, like DLLs usually are, the reason why an empty string for the [DllImport] attribute is good enough. Otherwise necessary, the compiler cannot know which DLL has this native code, that doesn't get sorted out until the linker runs and uses the import library of the native DLL.
The C++/CLI compiler goes a bit overboard emitting metadata for the pure native constructs in the code. But does its best to make them look as much as possible like their managed equivalents. Do note it is very incomplete, you can't for example see the names of the members of the AttackableUnit C++ class. You will find a lot of other spew in the assembly, a lot of CRT declarations make it into the metadata as well. The native linker does not do a terrific job of hiding it. Mostly because it doesn't have to, this code is pretty well isolated into the internal <Module> class.
Decompiling the machine code for native functions like GetHealth back to the original C++ code is not generally possible. Especially the optimizer built into the back-end of the compiler does a terrific job of making it next to impossible to guess what the original code might have looked like. Hex-Rays is usually mentioned as a machine code decompiler that does a credible job of at least correctly identifying code vs data.
I am working on a rather large codebase in which C++ functionality is P/Invoked from C#.
There are many calls in our codebase such as...
C++:
extern "C" int __stdcall InvokedFunction(int);
With a corresponding C#:
[DllImport("CPlusPlus.dll", ExactSpelling = true, SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
private static extern int InvokedFunction(IntPtr intArg);
I have scoured the net (insofar as I am capable) for the reasoning as to why this apparent mismatch exists. For example, why is there a Cdecl within the C#, and __stdcall within the C++? Apparently, this results in the stack being cleared twice, but, in both cases, variables are pushed onto the stack in the same reverse order, such that I do not see any errors, albeit the possibility that return information is cleared in the event of attempting a trace during debugging?
From MSDN: http://msdn.microsoft.com/en-us/library/2x8kf7zx%28v=vs.100%29.aspx
// explicit DLLImport needed here to use P/Invoke marshalling
[DllImport("msvcrt.dll", EntryPoint = "printf", CallingConvention = CallingConvention::Cdecl, CharSet = CharSet::Ansi)]
// Implicit DLLImport specifying calling convention
extern "C" int __stdcall MessageBeep(int);
Once again, there is both extern "C" in the C++ code, and CallingConvention.Cdecl in the C#. Why is it not CallingConvention.Stdcall? Or, moreover, why is there __stdcall in the C++?
Thanks in advance!
This comes up repeatedly in SO questions, I'll try to turn this into a (long) reference answer. 32-bit code is saddled with a long history of incompatible calling conventions. Choices on how to make a function call that made sense a long time ago but are mostly a giant pain in the rear end today. 64-bit code has only one calling convention, whomever is going to add another one is going to get sent to small island in the South Atlantic.
I'll try to annotate that history and relevance of them beyond what's in the Wikipedia article. Starting point is that the choices to be made in how to make a function call are the order in which to pass the arguments, where to store the arguments and how to cleanup after the call.
__stdcall found its way into Windows programming through the olden 16-bit pascal calling convention, used in 16-bit Windows and OS/2. It is the convention used by all Windows api functions as well as COM. Since most pinvoke was intended to make OS calls, Stdcall is the default if you don't specify it explicitly in the [DllImport] attribute. Its one and only reason for existence is that it specifies that the callee cleans up. Which produces more compact code, very important back in the days when they had to squeeze a GUI operating system in 640 kilobytes of RAM. Its biggest disadvantage is that it is dangerous. A mismatch between what the caller assumes are the arguments for a function and what the callee implemented causes the stack to get imbalanced. Which in turn can cause extremely hard to diagnose crashes.
__cdecl is the standard calling convention for code written in the C language. Its prime reason for existence is that it supports making function calls with a variable number of arguments. Common in C code with functions like printf() and scanf(). With the side effect that since it is the caller that knows how many arguments were actually passed, it is the caller that cleans up. Forgetting CallingConvention = CallingConvention.Cdecl in the [DllImport] declaration is a very common bug.
__fastcall is a fairly poorly defined calling convention with mutually incompatible choices. It was common in Borland compilers, a company once very influential in compiler technology until they disintegrated. Also the former employer of many Microsoft employees, including Anders Hejlsberg of C# fame. It was invented to make argument passing cheaper by passing some of them through CPU registers instead of the stack. It is not supported in managed code due to the poor standardization.
__thiscall is a calling convention invented for C++ code. Very similar to __cdecl but it also specifies how the hidden this pointer for a class object is passed to instance methods of a class. An extra detail in C++ beyond C. While it looks simple to implement, the .NET pinvoke marshaller does not support it. A major reason that you cannot pinvoke C++ code. The complication is not the calling convention, it is the proper value of the this pointer. Which can get very convoluted due to C++'s support for multiple inheritance. Only a C++ compiler can ever figure out what exactly needs to be passed. And only the exact same C++ compiler that generated the code for the C++ class, different compilers have made different choices on how to implement MI and how to optimize it.
__clrcall is the calling convention for managed code. It is a blend of the other ones, this pointer passing like __thiscall, optimized argument passing like __fastcall, argument order like __cdecl and caller cleanup like __stdcall. The great advantage of managed code is the verifier built into the jitter. Which makes sure that there can never be an incompatibility between caller and callee. Thus allowing the designers to take the advantages of all of these conventions but without the baggage of trouble. An example of how managed code could stay competitive with native code in spite of the overhead of making code safe.
You mention extern "C", understanding the significance of that is important as well to survive interop. Language compilers often decorate the names of exported function with extra characters. Also called "name mangling". It is a pretty crappy trick that never stops causing trouble. And you need to understand it to determine the proper values of the CharSet, EntryPoint and ExactSpelling properties of a [DllImport] attribute. There are many conventions:
Windows api decoration. Windows was originally a non-Unicode operating system, using 8-bit encoding for strings. Windows NT was the first one that became Unicode at its core. That caused a rather major compatibility problem, old code would not have been able to run on new operating systems since it would pass 8-bit encoded strings to winapi functions that expect a utf-16 encoded Unicode string. They solved this by writing two versions of every winapi function. One that takes 8-bit strings, another that takes Unicode strings. And distinguished between the two by gluing the letter A at the end of the name of the legacy version (A = Ansi) and a W at the end of the new version (W = wide). Nothing is added if the function doesn't take a string. The pinvoke marshaller handles this automatically without your help, it will simply try to find all 3 possible versions. You should however always specify CharSet.Auto (or Unicode), the overhead of the legacy function translating the string from Ansi to Unicode is unnecessary and lossy.
The standard decoration for __stdcall functions is _foo#4. Leading underscore and a #n postfix that indicates the combined size of the arguments. This postfix was designed to help solve the nasty stack imbalance problem if the caller and callee don't agree about the number of arguments. Works well, although the error message isn't great, the pinvoke marshaller will tell you that it cannot find the entrypoint. Notable is that Windows, while using __stdcall, does not use this decoration. That was intentional, giving programmers a shot at getting the GetProcAddress() argument right. The pinvoke marshaller also takes care of this automatically, first trying to find the entrypoint with the #n postfix, next trying the one without.
The standard decoration for __cdecl function is _foo. A single leading underscore. The pinvoke marshaller sorts this out automatically. Sadly, the optional #n postfix for __stdcall does not allow it to tell you that your CallingConvention property is wrong, great loss.
C++ compilers use name mangling, producing truly bizarre looking names like "??2#YAPAXI#Z", the exported name for "operator new". This was a necessary evil due to its support for function overloading. And it originally having been designed as a preprocessor that used legacy C language tooling to get the program built. Which made it necessary to distinguish between, say, a void foo(char) and a void foo(int) overload by giving them different names. This is where the extern "C" syntax comes into play, it tells the C++ compiler to not apply the name mangling to the function name. Most programmer that write interop code intentionally use it to make the declaration in the other language easier to write. Which is actually a mistake, the decoration is very useful to catch mismatches. You'd use the linker's .map file or the Dumpbin.exe /exports utility to see the decorated names. The undname.exe SDK utility is very handy to convert a mangled name back to its original C++ declaration.
So this should clear up the properties. You use EntryPoint to give the exact name of the exported function, one that might not be a good match for what you want to call it in your own code, especially for C++ mangled names. And you use ExactSpelling to tell the pinvoke marshaller to not try to find the alternative names because you already gave the correct name.
I'll nurse my writing cramp for a while now. The answer to your question title should be clear, Stdcall is the default but is a mismatch for code written in C or C++. And your [DllImport] declaration is not compatible. This should produce a warning in the debugger from the PInvokeStackImbalance Managed Debugger Assistant, a debugger extension that was designed to detect bad declarations. And can rather randomly crash your code, particularly in the Release build. Make sure you didn't turn the MDA off.
cdecl and stdcall are both valid and usable between C++ and .NET, but they should consistent between the two unmanaged and managed worlds. So your C# declaration for InvokedFunction is invalid. Should be stdcall. The MSDN sample just gives two different examples, one with stdcall (MessageBeep), and one with cdecl (printf). They are unrelated.
I created a DLL in C++ and loaded in C# with [DllImport].
Is __cdecl default in C++ when exporting without calling convention?
Is it okay to use CallingConvention.StdCall or CallingConvention.Winapi with the function __cdecl? (It worked in my test, and I don't use 'Variable Arguments')
Is __cdecl default in C++ when exporting without calling convention?
Yes.
Is it okay to use CallingConvention.StdCall or CallingConvention.Winapi with the function __cdecl?
No. Use CallingConvention.Cdecl. Using the wrong calling convention might appear to work for some functions, but it is wrong, and at some point you will be caught out.
Introduction to the problem:
I've got to control a certain device through API provided with a DLL file, LIB file, and c header files whose functions are declared as dllimport.
When I use the API in a C++ project everything worked just fine - I included the headers, lib , dll, and called the functions as declared in the header files.
The problem begins when trying to call those functions from a C#.NET project, using [DllImport] attribute: The functions were declared with the exact name and parameters, and running the code did not throw any exception. And yet the device did not respond at all, like the functions had never been actually called.
How it is declared in the C header:
int __declspec(dllimport) Init_Card_RTx(unsigned short device_num, unsigned short enabled_channels, unsigned short xmt_channels);
How it is declared in C#:
[DllImport(Path, CallingConvention = CallingConvention.Cdecl, EntryPoint = "Init_Card_RTx")]
public static extern int Init_Card_RTx(UInt16 device_num, UInt16 enabled_channels, UInt16 xmt_channels);
The questions:
Is that because the functions in the headers are declared dllimport?
In that case, do I have to wrap the DLL with C++ functions declared as dllexport?
What are the steps required for a C DLL to be accessible from C#?
In the C# project, do I have to include the LIB file as well? not just the DLL file itself?
Is that because the functions in the headers are declared dllimport?
Possibly. The functions need to be exported. Whether they are exported or not depends on how they DLL was compiled by whoever gave it to you. I'd guess that they should be though (or the C++ code would try import them and fail).
The first thing I do when troubleshooting this kind of thing is to load the DLL in Dependency Walker which will show you all the exported functions. If they're not showing up, they're not exported, and C# can't call them. If they are showing up, then you're ok and you don't need to change any of your C code or create any wrapper functions.
In that case, do I have to wrap the DLL with C++ functions declared as dllexport?
No. C# can only call C functions using DllImport. C++ does name mangling when exporting functions, which makes things a mess and generally not workable.
What you need to do is make your functions exported somehow. My guess is that they are already exported, but if not, you could make some wrapper functions like this.
int __declspec(dllexport) Init_Card_RTx(unsigned short device_num, unsigned short enabled_channels, unsigned short xmt_channels) {
// just call the other function here
}
These should make the function exported and you should see it show up in dependency walker.
What are the steps required for a C DLL to be accessible from C#?
The CLR has to be able to find the dll (usually you just put it in the same directory as the C# exe), and the functions have to be exported as C functions. That's pretty much it.
In the C# project, do I have to include the LIB file as well? not just the DLL file itself?
You don't need to include anything in the C# project at all, just the public static extern wrapper functions with their DllImport attributes on them. So long as the CLR can find the dll at runtime, that's all you need. If it can't find it at runtime, you should get an exception when you call the first imported method.
PS: Get Dependency walker. I can't recommend it more highly for this kind of thing
This kind of thing is always a pain in the butt. You have to make sure that the byte structure of the data being passed matches what your DLL is expecting, and exactly. The native structures in C# don't know that they are being passed externally, so you have to structure the code more rigorously.
See here for more info:
http://msdn.microsoft.com/en-us/library/awbckfbz(v=vs.110).aspx
The reason the functions are declared as dllimport is (correct me if I'm wrong) the the DLL is provided by your card vendor, that's ok because dllexport is only needed when building the DLL.
[DllImport(Path, CallingConvention = CallingConvention.Cdecl, EntryPoint = "Init_Card_RTx")]
The first argument Path is there only for ilustration purposes, am I rigth?
Can you open the DLL with depends.exe or PE Explorer(http://www.heaventools.com/download-pe-explorer.htm) and see the DLL's export table?
I'm asking this because the function name maybe decorated, that could happen if the DLL was compiled as C++ instead of plain C.
Try declacring it like this (you only do this once, in a CPP file, NOT a header)
extern "C" __declspec(dllexport) int __stdcall Init_Card_RTx(unsigned short device_num, unsigned short enabled_channels, unsigned short xmt_channels)
{
//
}
and in C#:
[DllImport("MyDll.dll")]
int Init_Card_RTx(ushort device_num, ushort enabled_channels, ushort xmt_channels);
you need to export it and declare with extern "C". __stdcall is convenient as it's the default on the .net side. I have a macro in my C++ project to make sure I type it the same everytime.
And yes, get dependencywalker....