How to load your own dynamic link library (DLL) in C #
Li Weima MSN: LiWeihua200204@hotmail.com
Abstract This article mainly tells how to implement the dynamic link library written in C language in C #, and how to match the C # and C languages when importing
Keywords C # C dynamic link library load data type matching
First, the background
Using new languages in the development of new languages Web Service, but in new projects, some old modules need to continue to use, generally written in C or C or Delphi, how to use the old module for For the developer, there are three available methods for choice: First, the C or C function is completely rewritten through C #, so the entire project code is more uniform, and it is convenient for maintenance. But although Microsoft and some books say, C # and C are close, but to write or have a painful thing, especially the pointers and memory operations in C ; second, encapsulate C or C functions into COM, call in C # COM is more convenient, just in the package, there is a need to handle the conversion between C or C types and COM types, and there are some troubles, and the additional COM also needs to register. The number of registrations can be more chaos; third, will encapsulate C or C functions It is simple to make a dynamic link library, the package is simple, and the workload is not large. So I decided to implement the method of loading the dynamic link library, so I generated how to call the custom dynamic link library in C #, I search on the related topics online, discover an article called the system API, but did not explain how to solve this Question, there is no relevant detailed description on the MSDN. Based on this, I decided to take my own goals from simple departure, gradually test it.
(Description: I have changed this here. I am afraid of trouble. I have rewritten the code is a long encryption calculation function. The code has more than 600 lines. It is not familiar with the algorithm itself. The algorithm is too much, and the algorithm is correct. The most feasible method is to have a less code, otherwise you can not affirm the algorithm with previous compatibility as long as there is a little error.
Second, technology implementation
Let's take a look at how to gradually realize the loading of the dynamic library, the type of type:
Dynamic link library function export definition, this doesn't need to say more, you can refer to the following macro:
#define libexport_api extern "c" __declspec (dllexport)
The first step, I first defined a simple function from a simple call, which simply implements an integer addition summary:
LIBEXPORT_API INT MYSUM (INT A, INT B) {RETURN A B;}
C # Define Import Definition:
Public Class Refcomm
{
[DLLIMPORT ("libencrypt.dll", entrypoint = "mysum", charset = charset.auto, callingconvention = calingconvention.stdcall)] Public static extern int mysum (int A, int b);
}
Call test in C #:
Int isum = refcomm. mysum (2, 3);
Run View Results ISUM is 5, the call is correct. The first test is completed, and it is description to call the custom dynamic link library function in C #. Step 2, I define the function of the string operation (simple origin, or using the previous function name), return the result is a string:
Libexport_api char * mysum (char * a, char * b) {sprintf (b, "% s", a) returnon a;}
C # Define Import Definition:
Public Class Refcomm
{
[DLLIMPORT ("libencrypt.dll", entrypoint = "mysum", charset = charset.auto, callingconvention = calingconvention.stdcall)] public static extern string mysum (String A, String B);
}
Call test in C #:
String strdest = "";
String stratmp = refcomm. MySum ("12345", strDest);
Run the result of the resultstrtmp is "12345", but StrDest is empty.
I modify the dynamic link library implementation, return the result is serial B:
Libexport_API Char * mysum (char * a, char * b) {sprintf (b, "% s", a) return b;}
Modify the C # import definition, modify the string B to REF mode:
Public Class Refcomm
{
[DLLIMPORT ("Libencrypt.dll", entrypoint = "mysum", charset = charset.auto, callingconvention = calingconvention.stdcall)] Public static extern string mysum (String A, Ref string b);
}
Repair test in C #:
String strdest = "";
String stratmp = refcomm. MySum ("12345", ref strdest);
Running View Results of Strtmp and StrDest are not correct, with invisible characters.
Modify the C # Import Definition, modify the Charset from Auto to ANSI:
Public Class Refcomm
{
[DLLIMPORT ("Libencrypt.dll", entrypoint = "mysum", charset = charset.ansi, callingconvention = calingconvention.stdcall)] Public static extern string mysum (String A, String B);
}
Repair test in C #:
String strdest = "";
String stratmp = refcomm. MySum ("12345", ref strdest);
Run the result of the resultstrtmp is "12345", but string strDest does not assign. The second step implementation function returns string, but there is no output in the function outlet parameters.
Modify the C # import definition again, modify the string B as reference (REF):
Public Class Refcomm
{
[DLLIMPORT ("libencrypt.dll", entrypoint = "mysum", charset = charset.ansi, callingconvention = calingconvention.stdcall)] public static extern string mysum (string a, ref string b);}
When the runtime call fails, you cannot continue.
In the third step, modify the dynamic link library implementation, modify B to double pointers:
LIBEXPORT_API CHAR * MYSUM (Char * a, char ** b) {sprintf ((* b), "% s", a) return * b;}
C # import definition:
Public Class Refcomm
{
[DLLIMPORT ("Libencrypt.dll", entrypoint = "mysum", charset = charset.ansi, callingconvention = calingconvention.stdcall)] Public static extern string mysum (String A, Ref string b);
}
Call test in C #:
String strdest = "";
String stratmp = refcomm. MySum ("12345", ref strdest);
Running View Results The strtmp and strDest are "12345" and the call is correct. The third step realizes the correct output of function outlet parameters.
In the fourth step, modify the dynamic link library implementation, implement the output of integer parameters:
LIBEXPORT_API INT MYSUM (INT A, INT B, INT * C) {* c = a b; return * c;}
C # import definition:
Public Class Refcomm
{
[DLLIMPORT ("Libencrypt.dll", entrypoint = "mysum", charset = charset.ansi, callingconvention = calingconvention.stdcall)] Public Static Extern Int MySum (Int A, INT B, Ref Int C);
}
Call test in C #:
INT C = 0;
Int isum = refcomm. mysum (2, 3, ref);
Operation View Results ISUM and C are 5, and the call is correct.
After the above, the above steps, basically mastered how to define dynamic library functions and how to import in C #, there is this basis, soon I implemented the call to the C-encryption function in C #, to this target implementation.
Third, conclusion
In C #, call the C to write a dynamic link library function. If an exit parameter output is required, you need to use a pointer. For a string, you need to use a double pointer. For the import definition of the C #, you need to use a reference (REF) definition.
For function return values, C # import definitions, and C dynamic library functions declare that the definition needs to be consistent, otherwise the function call failed.
When you define the import, you must pay attention to the Charset and CallingConvention parameters, otherwise the call failed or exception.
When running, the dynamic link library is placed in the directory of the C # program, I am a C # dynamic link library, the two dynamic link libraries are running in the same directory.