Sử dụng DLL trong .NET
Trong các chương trình viết trên nền .NET, ngoài việc sử dụng bộ thư viện được cung cấp bởi .NET Framework, đôi khi chúng ta có nhu cầu sử dụng các hàm được viết trên nền Windows, như các hàm API của Windows. Thông thường, các hàm này được cài đặt trong các thư viện liên kết động (DLL), được dịch bằng một trình dịch nào đó như MS Visual C++ hay Borland Delphi.
Các thư viện khi phát hành thường gồm 3 tệp, tệp tiêu đề có phần mở rộng .h chứa khai báo các hàm, tệp thư viện nhập có phần mở rộng .lib và tệp thư viện liên kết động có phần mở rộng .dll.
Để sử dụng các hàm của thư viện liên kết động trong .NET, chỉ cần tệp .dll là đủ, ngoài ra còn cần tệp .h để biết nguyên mẫu các hàm, từ đó khai báo các hàm trong .NET một cách đúng đắn.
Trong bài này, tôi giới thiệu cách sử dụng các hàm viết trong một thư viện liên kết động, được dịch bằng Visual C++ trong một chương trình viết trên nền .NET. Thư viện minh hoạ trong bài học này là thư viện đã được giới thiệu trong bài Thư viện liên kết động, môn học Lập trình Windows. Đây là một thư viện đơn giản với hai hàm: hàm tính luỹ thừa và hàm tính giai thừa.
Tệp tiêu đề của thư viện được khai báo như sau:
/* MyDll.h */
#ifndef __MYDLL_H__
#define __MYDLL_H__
#ifdef MYDLL_EXPORTS
#define MYDLLEXPORT _declspec(dllexport)
#else
#define MYDLLEXPORT _declspec(dllimport)
#endif
MYDLLEXPORT LONG CALLBACK Factorial(UINT);
MYDLLEXPORT DOUBLE CALLBACK Power(DOUBLE, UINT);
#endif // __MYDLL_H__
Tệp nguồn của thư viện:
/* MyDll.c */
#include
#include “MyDll.h”
LONG CALLBACK Factorial(UINT n)
{
return (n > 0)?n*Factorial(n – 1):1;
}
DOUBLE CALLBACK Power(DOUBLE x, UINT n)
{
return (n > 0)?x*Power(x, n – 1): 1;
}
Để sử dụng thư viện này trong .NET, dùng khai báo hàm với từ khoá extern và thuộc tính DllImport. Chương trình sau sẽ khai báo và sử dụng hai hàm này.
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace UsingDll {
class Program {
[DllImport("MyDll.dll")]
private static extern int Factorial(int n);
[DllImport("MyDll.dll")]
private static extern double Power(double x, int n);
static void Main(string[] args) {
Console.WriteLine(“2.0 to power 3 is {0}”,
Power(2.0, 3));
Console.WriteLine(“Factorial of 5 is {0}”,
Factorial(5));
}
}
}
Một trong những vấn đề thường gặp phải khi sử dụng hàm viết trên nền Windows trong .NET là kiểu dữ liệu giữa hai nền không giống nhau. Sau đây là một vài kiểu chuyển đổi để có thể gọi hàm một cách đúng đắn.
Kiểu số nguyên 1 byte:
Windows: TCHAR (char), BYTE (unsigned char).
.NET: sbyte, byte (C#), Byte (VB.NET).
Kiểu số nguyên 4 byte:
Windows: int, UINT (unsigned int), DWORD (unsigned int), LONG (long).
.NET: int (C#), Integer (VB.NET) hoặc Int32.
Kiểu số thực 4 byte:
Windows: float.
.NET: float (C#), Single (VB.NET)
Kiểu số thực 8 byte:
Windows: double.
.NET: double (C#), Double (VB.NET).
Kiểu xâu ký tự (vào):
Windows: LPCTSTR, LPSTR.
.NET: string (C#), String (VB.NET).
Kiểu xâu ký tự (ra):
Windows: LPSTR.
.NET: byte[], sbyte[] (C#), Byte [] (VB.NET)
Download:
- Mã nguồn thư viện.
- Mã nguồn chương trình.
Ghi chú:
- Các hàm trong DLL phải được dịch theo chế độ gọi stdcall. Để dịch theo chế độ stdcall, các hàm nên khai báo với chỉ thị _stdcall (WINAPI, CALLBACK) và đặt các tệp nguồn có phần mở rộng là .c. Để kiểm tra một hàm trong một DLL có sẵn có phải được gọi theo kiểu stdcall không, mở DLL và xem định dạng của hàm trong DLL phải có dạng _<Tên hàm>@<Độ dài tham số>. Ví dụ hai hàm trên sẽ có tên đầy đủ là: _Factorial@4 và _Power@12.
- Trong trường hợp lấy xâu ký tự ra từ hàm, cần phải truyền vào một mảng kiểu byte (ANSI) hoặc char (Unicode) đủ lớn, sau đó ghép các ký tự nhận được trong mảng để tạo thành xâu ký tự kiểu string.
Tháng Sáu 15, 2007 lúc 3:58 chiều
Ban co the huong dan them Import DLL vao VC++.net duoc khong.
Xin cam on
Tháng Sáu 16, 2007 lúc 9:38 sáng
@Hoatt
VC trong các bộ VS 7.1, VS 8.0 vẫn dịch ra chương trình chạy trên nền Windows, không phải trên nền .NET. Vì vậy cách sử dụng DLL tương tự như đối với VS 6.0, tức là cần #include tệp .h, liên kết với tệp .lib và sử dụng với tệp .dll
Tháng Mười 9, 2007 lúc 10:29 sáng
Thầy cho em hỏi ạ. Nếu thư viện dịch dạng W32 các hàm thuộc lớp thì gọi các hàm trong C# ra theo cách nào a. Mong thầy giúp em. Em cảm ơn Thầy ạ.
Tháng Mười 9, 2007 lúc 10:38 sáng
Thầy download thư viện Dll về và xem giúp em cách sử dụng hàm trong thư viện nhé.
http://files.myopera.com/binhlen/files/SqlSpatialClient.rar
Em cảm ơn Thầy rất nhiều ạ.
Tháng Ba 13, 2008 lúc 9:58 sáng
Chào thầy, em muốn hỏi thầy về cách tạo và sử dụng file dll trong C++. Bài viết bên trên của thầy em không hiểu lắm. Nếu thầy không thấy phiền có thể cho em một ví dụ nhỏ về cách tạo và sử dụng dll được không ạ. Chẳng hạn như ta viết một hàm nhỏ thôi, dịch ra dll rồi trong một chương trình khác ta lại sử dụng lại cái thư viện dll đó. Nhưng thầy có thể không dùng VC++ được không ạ, dùng C Free ấy, cái này viết thì em nghĩ mới hiểu được bản chất của nó. VC++ nó hỗ trợ hết rồi.
Tháng Ba 31, 2008 lúc 4:38 chiều
Chào Thầy,
E gặp vấn đề với kiểu dữ liệu unsigned char** từ Windows. Không hiểu nên map vào loại nào phía C# ?
Vì kiểu dữ liệu trả về là một buffer có độ dài biết trước chứ không phải chuổi (mãng của các ký tự kết thúc bằng ).
Mong thầy giúp giùm. Xin cám ơn.
Tháng Năm 20, 2008 lúc 9:20 sáng
nam
Tháng Ba 23, 2009 lúc 5:24 chiều
Gọi phương thức từ file .dll không nằm trên thư mục Bin??
Ví dụ tôi có 1 lybrary như sau
namespace LBR
{
public class class1
{
public string getstr(string _str)
{
return _str + “test ok”;
}
}
}
dịch nó ra file “LBR.DLL”
bây giờ mình tạo mới 1 project
Mình không add reference cái LBR.DLL đó mà để nó ở một thư mục nào đó thì có cách nào gọi và sử dụng cái “getstr()” trong class “class1″ đó không?
Cảm ơn các bạn nhiều!!!
Tháng Ba 26, 2009 lúc 7:31 sáng
lam sao de lien ket cac ham trong windows vao chuong trinh c++. Nho thay tra loi cho em voi .
Tháng Bảy 16, 2009 lúc 3:44 chiều
Gửi Thầy,
em có một vấn đề,
bây giờ em có một file DLL, ngoài ra, không có gì hết, không có file *.h, cũng không có file .lib; làm cách nào mình có thể export những class có trong file DLL này vào một file *.h để dùng trong project c++…
cảm ơn thầy