Why do I need to define DLLImport with EntryPoint attribute - c#

While going through SWig generated wrappers, I find that the PInvokes don't have any entry point defined, but some places do have an entry point. So what is the difference between them? When do I need to define an EntryPoint, and when do I not need to?
Defined without EntryPoint:
[DllImport("Kernel32.dll", CharSet = CharSet.Unicode)]
public static extern bool ReadFile(
HandleRef hndRef,
StringBuilder buffer,
int numberOfBytesToRead,
out int numberOfBytesRead,
int flag);
Defined with Entrypoint:
[DllImport("Kernel32.dll", CharSet = CharSet.Unicode, EntryPoint = "ReadFile")]
public static extern bool ReadFile2(
HandleRef hndRef,
StringBuilder buffer,
int numberOfBytesToRead,
out int numberOfBytesRead,
Overlapped2 flag);
Also why does the function have to be static as in public static extern? I assume that extern is telling the compiler that this method is defined externally?

The EntryPoint field serves to tell the .NET runtime which function to call from the DLL being invoked; if it's not set, the default is the same name that the .NET method declaration has. In your second example, omitting EntryPoint = "ReadFile" would result in the runtime trying to call a function named ReadFile2 (which does not exist).
The prototype needs to have the static and extern modifiers because the specification says so. It does not need to be public; controlling the visibility of the method is entirely up to you.

Related

How to call c++ unmanaged code in C# wrapper?

I have C# wrapper project that uses C++ unmanaged dll code with help of [DllImport] attribute and static extern methods. This is the preferred method described by MSDN.
The problem is that we can have only one of the c++ runner, which means we can't run tasks in parallel.
How to call the unmanaged C++ without using the dllimport + static extern methods so that when we instantiate one of the c# objects it instantiates a new c++ dll object
This is how we are calling C++ code right now.
public class FMU : IDisposable
{
[DllImport("FMU.dll", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
private static extern IntPtr Load(string fmuFileName, bool isCoSimulation, AddMessageDelegate messageDelegate, int arrayLocation);
[DllImport("FMU.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr Instantiate(IntPtr fmu, bool isCoSimulation, bool loggingOn, int nCategories, string[] categories);
[DllImport("kernel32", SetLastError = true)]
private static extern bool FreeLibrary(IntPtr hModule);

DLLImport a variable MFC dll

So I created the following test project:
[DllImportAttribute("TestMFCDLL.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern int test(int number);
private void button1_Click(object sender, EventArgs e)
{
int x = test(5);
}
Which works fine for my MFC dll that has the function test defined, however what I actually have is many MFC dlls that all share a common entry function and run differently based on my inputs. So basically I have tons of dlls that I cannot know at compile time what the name is, I just know that they have a function similar to how this program is setup, is there a way to import a dll based on run-time knowledge? Simply doing this returns an error:
static string myDLLName = "TestMFCDLL.dll";
[DllImportAttribute(myDLLName, CallingConvention = CallingConvention.Cdecl)]
An attribute argument must be a constant expression, typeof expression
or array creation expression of an attribute parameter type
If you want to dynamically load a DLL and use the functions in the DLL, then you'll need to do a little bit more. First you need to load the DLL dynamically. You can use LoadLibrary and FreeLibrary for that.
[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string dllName);
[DllImport("kernel32.dll")]
public static extern bool FreeLibrary(IntPtr hModule);
Second you need to get the address of the function in the DLL and call it.
[DllImport("kernel32.dll")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string functionName);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int Test(int number);
Putting that all together:
IntPtr pLib = LoadLibrary(#"PathToYourDll.DLL");
IntPtr pAddress = GetProcAddress(pLib, "test");
Test test = (Test)Marshal.GetDelegateForFunctionPointer(pAddress, typeof(Test));
int iRresult = test(0);
bool bResult = FreeLibrary(pLib);

P/Invoke from C#: Call functions of returned object

I have a native/unmanaged DLL and it has a "CreateObject" function which returns a pointer to the business object.. so the call would be sth. like:
[DllImport("MyDll.dll", CharSet = CharSet.Auto)]
private static extern IntPtr CreateObject();
Question:
The object is exposing public-functions like "Connect()" which i want to call, but i don't know how to "map" these calls so i have a simple method-signature like:
private bool Connect();
Any ideas?
The way to do this is to provide another PInvoke function which calls into a C function that does the method call
[DllImport("MyDll.dll", CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.I1)]
private static extern bool Connect(IntPtr businessObject);
Then in C you define the following
extern "C" {
bool Connect(Business* pObject) {
return pObject->Connect();
}
}
You have to wrap the C++ objects up in free functions:
bool Connect(MyObject* obj)
{
return obj->Connect();
}
and then export these from your DLL.
Alternatively you can make use of the fact that you are compiling with C++/CLI and export a managed C++/CLI class which can be consumed directly by your C# code.

Create an API in C# which can be called from it's DLL

I know the title is bit confusing for my question.
Let me explain:-
There are some DLLs written by my seniors and I use them in C# as follows:
Say, Existing DLL name is SeniorDLL and I want to use function SeniorFunc from that DLL.
What I do is:-
private delegate int SeniorFunc(IntPtr Blah);
[DllImport("kernel32")]
public extern static IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32", CharSet = CharSet.Ansi)]
public extern static IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
SeniorFunc fp_Senior;
and in function where I want to use this function, Before first function call I write:
IntPtr handle;
handle = IntPtr.Zero;
handle = LoadLibrary("<DLL Path>");
IntPtr fPtr = GetProcAddress(handle, "SeniorFunc");
fp_Senior = (SeniorFunc)Marshal.GetDelegateForFunctionPointer(fPtr, typeof(SeniorFunc));
and then I use this function via fp_Senior(<Parameter>);
Now I want to create such DLL for me in C# by which I'll be able to call functions from DLL.
Currently I created a DLL but I have create an instance of class in DLL and then have to access like ClassInstance.MyFunction(<Parameters>);
How can I get directly function calls without creating an instance?
In other words, (I don't know I am correct or wrong) How can I create APIs??
Thanks!!
You don't need an instance here, everything can be static. Something like this, with the necessary error checking added:
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
internal static class NativeMethods {
public static void SeniorFunc(IntPtr arg) {
if (fp_Senior == null) lookUpSenior();
fp_Senior(arg);
}
private static void lookUpSenior() {
loadSenior();
IntPtr addr = GetProcAddress(SeniorModule, "seniorfunc");
if (addr == IntPtr.Zero) throw new Win32Exception();
fp_Senior = (SeniorFuncDelegate)Marshal.GetDelegateForFunctionPointer(addr, typeof(SeniorFuncDelegate));
}
private static void loadSenior() {
if (SeniorModule == IntPtr.Zero) {
SeniorModule = LoadLibrary("mumble.dll");
if (SeniorModule == IntPtr.Zero) throw new Win32Exception();
}
}
private static IntPtr SeniorModule;
private delegate int SeniorFuncDelegate(IntPtr Blah);
private static SeniorFuncDelegate fp_Senior;
[DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
private extern static IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32", CharSet = CharSet.Ansi, SetLastError = true)]
public extern static IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
}
The point of keeping lookupSenior in a separate method is to allow SeniorFunc() to get inlined so it is fast. If you know you'll always use these functions in your program then you can also write a static constructor for the class and do the lookup there. Saves the null check but makes an exception a bit harder to interpret.
There is no such a thing as a method outside a class in C#. So if you must call a method, you have to specify the class name.
The difference with the DLLs you are currently using is that those DLLs are written in C/C++ or other non-.NET language which does not enforce a strict object-oriented approach like C# does.
Thus, nothing forces you to create an instance of a class when calling a method from a .NET library. If a method is declared as static, you can call it directly through ClassName.MethodName().

Parameter in C#

When I want get total value of memory in C# I found a kernel32 function in MSDN to invoke data from system. MSDN declare function this way:
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool GlobalMemoryStatusEx(ref MEMORYSTATUSEX lpBuffer);
but this don't work correctly. I change "ref" to "[In, Out]" then it work correctly.
How can tell me what is [In, Out] parameters in C#?
In: http://msdn.microsoft.com/de-de/library/system.runtime.interopservices.inattribute.aspx
Out: http://msdn.microsoft.com/de-de/library/system.runtime.interopservices.outattribute.aspx
Short: They control the way data is marshalled. In this case, where you specify both of them, it means that data is marshalled to both sides (caller and callee).
The out and the ref parameters are used to return values in the same variables, ref is enough if you don't know you will use it in or out.
Out if you just want to use the variable to receive data from the function, In if you just want to send data to the function.
ref if you want to send and receive data from a function, if you put nothing so it will be In by default
Note: ref and out parameters are very useful when your method needs to return more than one values.
The following definition works (define the MEMORYSTATUSEX as a class):
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GlobalMemoryStatusEx(MEMORYSTATUSEX lpBuffer);
[StructLayout(LayoutKind.Sequential)]
public sealed class MEMORYSTATUSEX {
public uint dwLength = (uint)Marshal.SizeOf(typeof(MEMORYSTATUSEX));
public uint dwMemoryLoad;
public ulong ullTotalPhys;
public ulong ullAvailPhys;
public ulong ullTotalPageFile;
public ulong ullAvailPageFile;
public ulong ullTotalVirtual;
public ulong ullAvailVirtual;
public ulong ullAvailExtendedVirtual;
}
Usage
var status = new MEMORYSTATUSEX();
GlobalMemoryStatusEx(status);
If you look at the function definition on MSDN it will tell you whether the parameters are In/Out:
BOOL WINAPI GlobalMemoryStatusEx(
__inout LPMEMORYSTATUSEX lpBuffer
);
In general if it says out, you should use a ref parameter, it makes is easier on any future developers trying to figure out how the code is working. When looking at the function call, you know the developer meant for the argument to be affected.

Categories

Resources