Giới thiệu
DLL (Dynamic Link Library) là một dạng mô-đun để chứa các hàm (function) và dữ liệu phục vụ cho các ứng dụng hoặc cho DLL khác. Bằng cách này, DLL giúp tiết kiệm bộ nhớ khi chia sẻ các hàm của nó cho nhiều chương trình cùng truy xuất tại một thời điểm.
Bài viết này sẽ giúp bạn “tái sử dụng” các DLL ngày xửa ngày xưa trong môi trường C#, bằng cách gọi các hàm export chứa trong nó.
Lưu ý:
- Khi .NET ra đời, Microsoft đã phát triển thêm một dạng khác của DLL là Class Library khá tiện lợi. Tuy nhiên, bài viết này chỉ đề cập đến dạng DLL “cổ điển”.
- Để thử nghiệm, bạn chỉ cần có Visual Studio 7.1 (VS 2003) trở lên.
Tạo file DLL phục vụ thử nghiệm
Trước hết, chúng ta cần một file DLL phục vụ thử nghiệm. Bạn tạo một project Visual C++ mới, chọn Configuration type là “Dynamic Library (.dll)”. Sau đó tạo mới 2 file như sau:
- File “TestAPI.cpp”: chứa nội dung chính của DLL, với 2 hàm export. Hàm GetAge “bình dân” với kiểu trả về và tham số đều là kiểu dữ liệu nguyên thủy (integer). Hàm GetUser() phức tạp hơn một chút với một tham chiếu dạng struct “UserInfo”.
- File “TestAPI.def”: khai báo các hàm được export.
File “TestAPI”
Mã:
//khai báo 1 struct thử nghiệmstruct UserInfo{ int id; int age; char name[30];}; //hàm có giá trị trả về và 1 tham số là kiểu int__declspec(dllexport) DWORD _stdcall GetAge(int id){ if (id == 1) { return 10; } return -1;} //hàm có tham số là một biến tham chiếu struct__declspec(dllexport) DWORD _stdcall GetUser(int id, UserInfo &user){ if (id == 1) { user.id = 1; user.age = 10; strcpy(user.name, "sonhn"); return 0; } return -1;} //entry point cho DLLBOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved){ return TRUE;}
File “TestAPI.def”
Mã:
LIBRARY "TestDLL"DESCRIPTION 'sample dll Interface Windows DLL EXPORTS ; Explicit exports can go here GetAge GetUser
Biên dịch project này để sinh ra file “TestDLL.dll”.
Tạo project C# thử nghiệm
Trước hết, tạo một project C# dạng Console Application (cho đơn giản!). Sau đó, hãy copy file “TestDLL.dll” vào folder “\bin\Debug” của project này.
Bạn sẽ thấy nội dung của file .cs chính có dạng như bên dưới. Lưu ý, để import và gọi các hàm trong DLL, bạn cần khai báo thêm gói InteropServices như dòng số 2.
Mã:
Using System;Using System.Runtime.InteropServices; //cần để thao tác với DLL namespace CSharp{ class TestCS { static void Main(string[] args) { /ội dung đặt ở đây } }}
Gọi hàm cơ bản trong DLL từ C#
Để gọi một hàm trong DLL từ C#, chúng ta phải làm 3 bước:
- Import file DLL
- Khai báo một “nguyên mẫu” hàm sẽ gọi
- Gọi hàm
Ví dụ:
- Để import và khai báo nguyên mẫu cho hàm GetAge(int id), chúng ta chỉ cần dùng 2 dòng code sau:
Mã:
[DllImport("TestDLL.DLL", EntryPoint="GetAge")] //import hàmpublic static extern int GetAge(int id); //khai báo nguyên mẫu
- Sau đó, sử dụng hàm GetAge() này như thể nó đang nằm trong project C#:
Mã:
int age = GetAge(1);Console.WriteLine("age = " + age);
Khi tham số hàm là các kiểu dữ liệu phức tạp
Với tham số hàm là kiểu string, struct… thì mọi chuyện phức tạp hơn một chút, ví dụ:
- Để chứa chuỗi ký tự, C# có kiểu string, nhưng ANSI C++ lại là một mảng kiểu char kết thúc bằng giá trị ‘0’.
- Với dữ liệu dạng struct, hãy nhìn vào cấu trúc UserInfo ở ví dụ trên: data struct này được khai báo bên DLL thuộc project VC++. Khi sang bên project C#, chỉ có… trời mới hiểu UserInfo là cái quái gì!
Giải quyết?
Với biến string, ta dùng những “chỉ dẫn” để bắt C# “hiểu” và thao tác với dữ liệu của C++. Với biến struct, ta khai báo lại một data struct tương tự bên project C#, kèm theo một số chỉ dẫn của C#.
Ví dụ: khai báo cấu trúc UserInfo tương tự bên C#
Mã:
[StructLayout(LayoutKind.Sequential)]public struct UserInfo{ public int id; public int age; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 30)] public string name; //tương đương char name [30] trong C++};
Chú ý dòng thứ 1 và 6, đây là những “chỉ dẫn” giúp C# quản lý các kiểu dữ liệu không thuộc phạm vi của nó.
Và sau đó là sử dụng “vô tư”:
Mã:
UserInfo user = new UserInfo();int errCode = GetUser(1, ref user);Console.WriteLine("id = " + user.id + ", name = " + user.name + ", age = " + user.age);
View more random threads:
Dưới ánh nắng mặt trời đang lên, những đống pallet nhựa An Giang trải dài mênh mông như những bức tranh tự nhiên đầy sắc màu. Mỗi chiếc pallet nhựa không chỉ là một vật dụng thông thường mà còn là...
Pallet nhựa An Giang giao hàng...