C # dynamic invocation of DLL functions written in C + +

Source: Internet
Author: User

C # dynamic invocation of DLL functions written in C + +

Dynamically loaded DLLs require the use of Windows API functions: LoadLibrary, GetProcAddress, and FreeLibrary. We can use these three functions in C # using DllImport.

[DllImport ("Kernel32")]
public static extern int GetProcAddress (int handle, String funcname);

[DllImport ("Kernel32")]
public static extern int LoadLibrary (String funcname);

[DllImport ("Kernel32")]
public static extern int FreeLibrary (int handle);

when we invoke the functions in the DLL dynamically in C + +, our general approach is to
Suppose there is an export function in the DLL, the function prototype is as follows:
BOOL __stdcall foo (Object &object, lpvoid lpreserved);

1. First define the corresponding function pointers:
typedef BOOL (__stdcall *pfoo) (Object &object, lpvoid lpreserved);

2. Call LoadLibrary to load the DLL:
HInstance HInst =:: Loadlibraryw (Dllfilename);

3. Call the GetProcAddress function to get the address of the function to be called:
Pfoo foo = (pfoo) GetProcAddress (hInst, "foo");
if (foo = = NULL)
{
FreeLibrary (HInst);
return false;
}

4. Call the Foo function:
BOOL BRet = Foo (object, (LPVOID) NULL);

5, after use should release the DLL:
FreeLibrary (HInst);

So what should you do in C #? Method Basically, we use delegates instead of C + + function pointers to get an instance of a delegate through the new function GetDelegateForFunctionPointer. NET Framework 2.0:

The following encapsulates a class in which we can invoke functions in a DLL dynamically in C #:

public class Dllwrapper
{
<summary>
API LoadLibrary
</summary>
[DllImport ("Kernel32")]
public static extern int LoadLibrary (String funcname);

<summary>
API GetProcAddress
</summary>
[DllImport ("Kernel32")]
public static extern int GetProcAddress (int handle, String funcname);

<summary>
API FreeLibrary
</summary>
[DllImport ("Kernel32")]
public static extern int FreeLibrary (int handle);

<summary>
Converted to the corresponding delegate through the unmanaged function name, by Jingzhongrong
</summary>
<param name= "Dllmodule" > DLL handle obtained through LoadLibrary </param>
<param name= "functionname" > Non-managed function name </param>
<param name= "T" > corresponding delegate type </param>
<returns> delegate instances, which can be cast to the appropriate delegate type </returns>
public static Delegate getfunctionaddress (int dllmodule, string functionname, Type t)
{
int address = GetProcAddress (Dllmodule, functionname);
if (address = = 0)
return null;
Else
Return Marshal.getdelegateforfunctionpointer (new IntPtr (address), T);
}

<summary>
Converts a IntPtr instance representing a function address into a corresponding delegate, by Jingzhongrong
</summary>
public static Delegate Getdelegatefromintptr (IntPtr address, Type t)
{
if (address = = IntPtr.Zero)
return null;
Else
return Marshal.getdelegateforfunctionpointer (address, t);
}

<summary>
Converts an int representing a function address into a corresponding delegate, by Jingzhongrong
</summary>
public static Delegate getdelegatefromintptr (int address, Type t)
{
if (address = = 0)
return null;
Else
Return Marshal.getdelegateforfunctionpointer (new IntPtr (address), T);
}
}

Through this class, we call DLLs like this:

1, the Declaration of the corresponding delegation (the correct declaration is important, otherwise it can not be called success, followed by detailed introduction).

2. Load DLL:
int hmodule = Dllwrapper.loadlibrary (Dllfilepath);
if (hmodule = = 0)
return false;

3, obtain the corresponding delegate instance:
Foo foo = (foo) dllwrapper.getfunctionaddress (hmodule, "foo", typeof (Foo));
if (foo = = null)
{
Dllwrapper.freelibrary (hmodule);
return false;
}

4. Call Function:
Foo (...);

5,. NET does not automatically release dynamically loaded DLLs, so we should release the DLLs ourselves after we have finished using the DLLs:
Dllwrapper.freelibrary (hmodule);

Here we discuss how the delegate should be declared, and in practice I find that using the DllImport method and the dynamic invocation method are somewhat different in C # for the declaration of a function prototype in a DLL, and I describe the declaration of the delegate in the dynamic invocation:

1, first of all, it should be noted that the type in C + + and the corresponding relationship in C #, such as a long in C + + should correspond to Int32 in C # instead of a long, otherwise it will result in an error in the call result.

2, the structure of the declaration using StructLayout to set the corresponding layout of the structure, specifically, see MSDN:

Using LayoutKind to specify the layout order of members in a structure, you can generally use sequential:
[StructLayout (LayoutKind.Sequential)]
struct STRUCTVERSIONINFO
{
public int majorversion;
public int minorversion;
}
In addition, you can declare a struct in C # as Class if you use the inner type alone without using another string, struct, or class:
[StructLayout (LayoutKind.Sequential)]
Class Structversioninfo
{
public int majorversion;
public int minorversion;
}

Corresponds to a declaration in C + +:
typedef struct _VERSION_INFO
{
int majorversion;
int minorversion;
} version_info, *pversion_info;

If a string is used in the structure, it is best to specify the appropriate character set:
[StructLayout (Layoutkind.sequential,charset=charset.unicode)]

Some of the commonly used declarations correspond to relationships (in structs):
C + +: array of strings
wchar_t comments[120];
C#:
[MarshalAs (UnmanagedType.ByValTStr, SizeConst = 120)]
public string Comments;

C + +: struct members
Version_info ver;
C#
Publicstructversioninfo ver;

C + +: function pointer declaration
Pfoo Pfoo; See the previous section of the article for a specific statement
C#:
Publicintptr Pfoo; You can also pfoo for public int;
Different declarative methods can use the corresponding function of the above Dllwrapper class to get the corresponding delegate instance

If the union is used in the structure, you can use FieldOffset to specify a specific location.

3, the delegation of the Declaration:

When a DLL function written in C + + needs to pass through the pointer, it will have a structure: the following declaration:
void GetVersionInfo (Version_info *ver);
For structs declared as Class in C # (when Version_info is declared as Class)
Delegate Voidgetversioninfo (Version_info ver);
If the struct is declared as a struct, then the following declaration should be used:
Delegate Voidgetversioninfo (Refversion_info ver);
Note: You should use the REF keyword.


If a DLL function needs to pass in a string, such as this:
BOOL __stdcall jingzhongrong1 (const wchar_t* lpfilename, int* filenum);
You should declare the delegate as follows in C # when you use a delegate to invoke a function:
delegate BOOL Jingzhongrong1 (
[MarshalAs (UNMANAGEDTYPE.LPWSTR)] String FileName,
ref int filenum);
Note: You should use [MarshalAs (UNMANAGEDTYPE.LPWSTR)] and string to declare.


If you want to leave a string in the DLL function, for example:
void __stdcall Jingzhongrong2 (
wchar_t* lpFileName,//string to outgoing
int* Length);
Then we declare the delegate as follows:
Use a delegate to remove a string from an unmanaged function's arguments,
You should declare this and prepare enough space for StringBuilder before calling.
delegate void Jingzhongrong2 (
[MarshalAs (UNMANAGEDTYPE.LPWSTR)] StringBuilder lpFileName,
ref int Length,
);
Before using a function, you should declare enough space for the StringBuilder to hold the string:
StringBuilder fileName = new StringBuilder (filenamelength);

Reference: http://www.2cto.com/kf/201007/52562.html

C # dynamic invocation of DLL functions written in C + +

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.