Call stdlib.h functions from C# - c#

For different purposes I need to provide an interface that implementents the following functions in C#
malloc
calloc
realloc
free
But I would prefer to not to code it myself (why reinvent the wheel).
A better solution would be when my alloc-functions was called, I would simplely call the alloc-functions in stdlib.h, the interface is made so I "just" need to call those functions.
The question is, how do I access the functions in the stdlib.h from C#?
I know about platform invoke, and I am getting better at it. But for platform invoke to work, I need a .dll
And I don't know which .dll implements the stdlib.h

I don't think this sounds like the best solution for your problem. But to answer the question you first need to decide which C runtime to use. One possibility is the system component in msvcrt.dll. Access the functions like this:
[DllImport("msvcrt.dll", CallingConvention=CallingConvention.Cdecl)]
static extern IntPtr malloc(IntPtr size);
[DllImport("msvcrt.dll", CallingConvention=CallingConvention.Cdecl)]
static extern void free(IntPtr ptr);
[DllImport("msvcrt.dll", CallingConvention=CallingConvention.Cdecl)]
static extern IntPtr calloc(IntPtr num, IntPtr size);
[DllImport("msvcrt.dll", CallingConvention=CallingConvention.Cdecl)]
static extern IntPtr realloc(IntPtr ptr, IntPtr size);
However, the official position from MS is that msvcrt.dll is private and not for use by third party applications. So you might prefer to link to a C++ runtime associated with a specific version of MSVC. For example, to link to the VS2013 runtime specify msvcr120.dll. This of course would require you to distribute that runtime.

Related

Unmanaged signature when importing Visual c++ DLL in c#

I have a DLL that was developed in Visual C++, and I've started importing it's functionality to a c# project using DllImport. I've already implemented a few methods and they work well.
For that specific method I'm getting the following error:
Additional information: A call to PInvoke function 'SdkTest!SdkTest.Program::CLIENT_RealPlay' 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.
The c++ method I'm trying to implement has this signature:
CLIENT_NET_API LLONG CALL_METHOD CLIENT_RealPlay(LLONG lLoginID, int nChannelID, HWND hWnd);
With the following definitions:
#define CLIENT_NET_API __declspec(dllimport)
#define CALL_METHOD __stdcall
#define LLONG LONG
My c# impelmentation is the following:
[DllImport("dhnetsdk.dll")]
public static extern long CLIENT_RealPlay(long lLoginID, int nChannelID, IntPtr hWnd);
(I've read that HWND equivalent in c# is IntPtr, but I've also tried to put int, long, object...)
I also tried doing DllImport in the following way (As suggested in some posts and worked for some other methods I'm using):
[DllImport("dhnetsdk.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
No matter what I try I'm getting the same error. What am I miss understanding? If an internal exception in the c++ code is thrown, what kind of exception will I get in my code?
#define LLONG LONG
Now, LONG maps to long, which is a signed 32 bit type on Windows. Therefore, using long in your C# code is wrong because C# long is a 64 bit type. You need to use int instead. Like this:
[DllImport("dhnetsdk.dll")]
public static extern int CLIENT_RealPlay(int lLoginID, int nChannelID, IntPtr hWnd);
The c++ function is declared with calling convention stdcall, but you are calling it with cdecl.
In my experience, call stack corruptions are mostly caused by using the wrong calling convention.

Call to external DLL from C# with integer pointer

I'm trying to call an external .dll function from c#. The doc for the dll defines the function:
int funcName(int *retVal)
I've tried various configurations and always the unbalanced stack error from p/invoke; My c# code currently looks like this:
[DLLImport("dllName");
unsafe static extern int funcName(ref IntPtr retVal);
unsafe IntPtr retNum;
int status = funcName(ref retNum);
Any ideas are appreciated!
Your p/invoke declaration has the wrong parameter type.
ref Int32 is the correct match for int*.
IntPtr can also work.
ref IntPtr would be int**. Definitely not what you want.
Use
[DLLImport("dllName")]
static extern int funcName(ref Int32 retVal);
Also make sure that the calling convention matches. You should never use a dllexport in C or C++ without also using an explicit calling convention, and then the C# DllImport needs to have the matching convention.
Generally the prototype in C++ should be
extern "C" int __stdcall funcName(int* arg);
Is there a header file provided for C and C++ clients that you could check to verify the signature?

Marshalling arrays of VARIANT using P/Invoke

Situation:
I have a managed (C#, .NET 2.0) application which uses an unmanaged (C++) DLL using P/Invoke. Along with the "simple" methods (POD arguments/return value) there's a requirement to pass a boost::variant value arrays to the code. The reason for it is that these methods pass report data (similar to Excel cells, which can be of any type). C# code accepts them as boxed "object"'s.
The previous implementation called for use of SafeArray of COM VARIANT's. However, due to poor coding/not testing it, the marshalling turned out to be leaking memory. Now I have to find another option for marshalling the data.
Previous implementation looked like this:
C++:
extern "C" __declspec(dllexport) void GetReport(VARIANT& output) {
// ... here a SafeArray of VARIANT values was created
output.vt = VT_VARIANT | VT_ARRAY;
output.parray = safeArray;
}
C#
[DllImport("CppLibrary.dll")]
private static extern void GetReport(out object output);
//....
object data;
GetReport(data);
object rows = data as object[];
This specific implementation leaks memory by not freeing up the interop structures.
I've tried to change the prototypes by including SafeArray marshalling directives:
C++
extern "C" __declspec(dllexport) void GetReport(SAFEARRAY output) { // Also tried SAFEARRAY*, SAFEARRAY&, VARIANT, VARIANT&, VARIANT*
// Internal stuff
}
C#
private static extern void GetReport([Out, MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)]ref object[] output);
However, the only things I've achieved were either an empty resulting object(s), or crash due to memory corruption/stack overflow.
Problem:
How to correctly marshal such data type (array of VARIANT-typed structures) to C#?
I can make the C++ DLL a COM one, but this will require rewriting quite a handful of code. Is there any simpler way out of the situation? Maybe I'm missing something.
There is this example: http://limbioliong.wordpress.com/2011/03/20/c-interop-how-to-return-a-variant-from-an-unmanaged-function/
In the end they use directly an IntPtr (they use it as a return value, you would have to use it as a out IntPtr), then Marshal.GetObjectForNativeVariant(), VariantClear() and Marshal.FreeCoTaskMem() from the C# side, while on the C/C++ side the VARIANT was allocated with CoTaskMemAlloc().
[DllImport("MyDLL.dll", CallingConvention = CallingConvention.StdCall)]
static extern void MyFunction(out IntPtr ptr);
[DllImport("oleaut32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
static extern Int32 VariantClear(IntPtr pvarg);
IntPtr pVariant;
MyFunction(out pVariant);
object objRet = Marshal.GetObjectForNativeVariant(pVariant);
VariantClear(pVariant);
Marshal.FreeCoTaskMem(pVariant);
pVariant = IntPtr.Zero;
Clearly you could expose another C function in your dll that frees the VARIANT (it's always correct to expose Free methods in your library, so that caller can use them and not ask himself "how should I free this memory?")

Proper calling convention of unmanaged DLL function

I'm trying to write a bare-bones ultra-simple light-weight wrapper for the LibVLC DLL Library. I don't need access to much, just the ability to play pause and stop media files. I'm looking at the documentation and this other link I found that explains an older version of LibVLC, but it's outdated for the most recent version. I also tried LibVLC.Net but it too is outdated and I can't find what I'm looking for in the source code to match it to the functions I'm trying to export.
I have the following signature I'm trying to export:
libvlc_new (int argc, const char *const *argv)
The description:
argc the number of arguments (should be 0)
argv list of arguments (should be NULL)
And this is the method I'm trying.
[DllImport("libvlc", EntryPoint = "libvlc_new")]
public static extern IntPtr New(Int32 argc, String[] argv);
The description suggests it should be an array, and I think the problem is the second argument. I've tried:
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr)] String[] argv
as according to here, and there are a couple of other options such as a String and StringBuilder as suggested here but it still happens that every time I call the function I get an Imbalanced PInvoke stack.
I need to know what the proper calling convention of this, and very likely several other, functions are. A "PInvoke For Dummies" online reference would be super good.
Not much point in declaring the argument type if only NULL is permitted. Just declare it IntPtr and pass IntPtr.Zero.
The debugger is pointing out that you forgot to declare the CallingConvention. It is not the default for .NET, this is a __cdecl function. So the proper declaration would be:
[DllImport("libvlc", EntryPoint = "libvlc_new",
CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr New(int argc, IntPtr argv);
Called as:
New(0, IntPtr.Zero);
Do try to pick a better name...

When Importing a DLL Why Do Methods Have To Be Declared Static and Extern?

As the title asks, when you import a DLL such as User32.dll and declare methods to call methods on that DLL why do the methods need to be declared as Static and Extern.
I.E, this was taken from another StackOverflow answer, but demonstrates what I'm asking.
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, UIntPtr dwExtraInfo);
static - As they do not need instance of the class, those method's are call to system API and do not need any Initialization, can be used in static / non-static block
extern - The extern modifier is used to declare a method that is implemented externally. Since API methods are not declared in the class file itself, extern tell the compiler that method declared else-where.
While I do not really know whether there are technical details to this, I'd say the reasons are:
static
Methods that reside in external DLLs can not be bound to any object instance. If they were bound to an object instance, the DLL would have to track which instance is calling the method every time.
extern
I guess this is just a keyword telling the compiler to insert code for binding the DLL instead of expecting the method to be implemented in C#.

Categories

Resources