DLL - Cara Menulis

Pertama, kita akan membahas masalah dan persyaratan yang harus Anda pertimbangkan saat mengembangkan DLL Anda sendiri.

Jenis DLL

Saat Anda memuat DLL dalam aplikasi, dua metode penautan memungkinkan Anda memanggil fungsi DLL yang diekspor. Dua metode penautan adalah -

  • tautan dinamis waktu muat, dan
  • penautan dinamis run-time.

Penautan dinamis waktu muat

Dalam penautan dinamis waktu muat, aplikasi membuat panggilan eksplisit ke fungsi DLL yang diekspor seperti fungsi lokal. Untuk menggunakan penautan dinamis waktu muat, berikan file header (.h) dan file library impor (.lib), saat Anda mengompilasi dan menautkan aplikasi. Saat Anda melakukan ini, linker akan menyediakan sistem dengan informasi yang diperlukan untuk memuat DLL dan menyelesaikan lokasi fungsi DLL yang diekspor pada waktu pemuatan.

Tautan dinamis waktu proses

Dalam penautan dinamis runtime, aplikasi memanggil fungsi LoadLibrary atau fungsi LoadLibraryEx untuk memuat DLL saat runtime. Setelah DLL berhasil dimuat, Anda menggunakan fungsi GetProcAddress, untuk mendapatkan alamat fungsi DLL yang diekspor yang ingin Anda panggil. Saat Anda menggunakan penautan dinamis runtime, Anda tidak memerlukan file library impor.

Daftar berikut menjelaskan kriteria aplikasi untuk memilih antara penautan dinamis waktu muat dan penautan dinamis waktu proses -

  • Startup performance - Jika kinerja permulaan awal aplikasi penting, Anda harus menggunakan tautan dinamis run-time.

  • Ease of use- Dalam tautan dinamis waktu buka, fungsi DLL yang diekspor mirip dengan fungsi lokal. Ini membantu Anda memanggil fungsi-fungsi ini dengan mudah.

  • Application logic- Dalam penautan dinamis runtime, aplikasi dapat bercabang untuk memuat modul yang berbeda sesuai kebutuhan. Ini penting saat Anda mengembangkan versi banyak bahasa.

Titik Masuk DLL

Saat Anda membuat DLL, Anda dapat secara opsional menentukan fungsi titik masuk. Fungsi titik masuk dipanggil saat proses atau utas menempelkan dirinya sendiri ke DLL atau melepaskan diri dari DLL. Anda dapat menggunakan fungsi titik masuk untuk menginisialisasi atau menghancurkan struktur data seperti yang dipersyaratkan oleh DLL.

Selain itu, jika aplikasi multithread, Anda dapat menggunakan penyimpanan lokal thread (TLS) untuk mengalokasikan memori yang bersifat pribadi ke setiap thread dalam fungsi titik masuk. Kode berikut adalah contoh fungsi titik masuk DLL.

BOOL APIENTRY DllMain(
   HANDLE hModule,	   // Handle to DLL module 
   DWORD ul_reason_for_call, 
   LPVOID lpReserved )     // Reserved
{
   switch ( ul_reason_for_call )
   {
      case DLL_PROCESS_ATTACHED:
      // A process is loading the DLL.
      break;
      
      case DLL_THREAD_ATTACHED:
      // A process is creating a new thread.
      break;
      
      case DLL_THREAD_DETACH:
      // A thread exits normally.
      break;
      
      case DLL_PROCESS_DETACH:
      // A process unloads the DLL.
      break;
   }
   return TRUE;
}

Ketika fungsi titik masuk mengembalikan nilai FALSE, aplikasi tidak akan mulai jika Anda menggunakan tautan dinamis waktu muat. Jika Anda menggunakan tautan dinamis runtime, hanya DLL individual yang tidak akan dimuat.

Fungsi titik masuk seharusnya hanya melakukan tugas inisialisasi sederhana dan tidak boleh memanggil fungsi pemuatan atau penghentian DLL lainnya. Misalnya, dalam fungsi titik masuk, Anda tidak boleh secara langsung atau tidak langsung memanggilLoadLibrary fungsi atau LoadLibraryExfungsi. Selain itu, Anda tidak boleh memanggilFreeLibrary berfungsi saat proses dihentikan.

WARNING- Dalam aplikasi multithread, pastikan bahwa akses ke data global DLL disinkronkan (aman untuk thread) untuk menghindari kemungkinan kerusakan data. Untuk melakukannya, gunakan TLS untuk menyediakan data unik untuk setiap utas.

Mengekspor Fungsi DLL

Untuk mengekspor fungsi DLL, Anda dapat menambahkan kata kunci fungsi ke fungsi DLL yang diekspor atau membuat file definisi modul (.def) yang mencantumkan fungsi DLL yang diekspor.

Untuk menggunakan kata kunci fungsi, Anda harus mendeklarasikan setiap fungsi yang ingin Anda ekspor dengan kata kunci berikut -

__declspec(dllexport)

Untuk menggunakan fungsi DLL yang diekspor dalam aplikasi, Anda harus mendeklarasikan setiap fungsi yang ingin Anda impor dengan kata kunci berikut -

__declspec(dllimport)

Biasanya, Anda akan menggunakan satu file header yang memiliki define pernyataan dan ifdef pernyataan untuk memisahkan pernyataan ekspor dan pernyataan impor.

Anda juga dapat menggunakan file definisi modul untuk menyatakan fungsi DLL yang diekspor. Saat Anda menggunakan file definisi modul, Anda tidak perlu menambahkan kata kunci fungsi ke fungsi DLL yang diekspor. Dalam file definisi modul, Anda mendeklarasikanLIBRARY pernyataan dan EXPORTSpernyataan untuk DLL. Kode berikut adalah contoh file definisi.

// SampleDLL.def
//
LIBRARY "sampleDLL"

EXPORTS
   HelloWorld

Tulis Contoh DLL

Di Microsoft Visual C ++ 6.0, Anda dapat membuat DLL dengan memilih file Win32 Dynamic-Link Library jenis proyek atau MFC AppWizard (dll) Jenis proyek.

Kode berikut adalah contoh DLL yang dibuat dalam Visual C ++ dengan menggunakan jenis proyek Perpustakaan Dynamic-Link Win32.

// SampleDLL.cpp

#include "stdafx.h"
#define EXPORTING_DLL
#include "sampleDLL.h"

BOOL APIENTRY DllMain( HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved )
{
   return TRUE;
}

void HelloWorld()
{
   MessageBox( NULL, TEXT("Hello World"), 
   TEXT("In a DLL"), MB_OK);
}
// File: SampleDLL.h
//
#ifndef INDLL_H
#define INDLL_H

   #ifdef EXPORTING_DLL
      extern __declspec(dllexport) void HelloWorld() ;
   #else
      extern __declspec(dllimport) void HelloWorld() ;
   #endif

#endif

Memanggil Sample DLL

Kode berikut adalah contoh dari proyek Aplikasi Win32 yang memanggil fungsi DLL yang diekspor di SampleDLL DLL.

// SampleApp.cpp 

#include "stdafx.h"
#include "sampleDLL.h"

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{ 	
   HelloWorld();
   return 0;
}

NOTE - Dalam penautan dinamis waktu muat, Anda harus menautkan pustaka impor SampleDLL.lib yang dibuat saat Anda membuat proyek SampleDLL.

Dalam runtime dynamic linking, Anda menggunakan kode yang mirip dengan kode berikut untuk memanggil fungsi DLL yang diekspor SampleDLL.dll.

...
typedef VOID (*DLLPROC) (LPTSTR);
...
HINSTANCE hinstDLL;
DLLPROC HelloWorld;
BOOL fFreeDLL;

hinstDLL = LoadLibrary("sampleDLL.dll");

if (hinstDLL != NULL)
{
   HelloWorld = (DLLPROC) GetProcAddress(hinstDLL, "HelloWorld");
	
   if (HelloWorld != NULL)
      (HelloWorld);

   fFreeDLL = FreeLibrary(hinstDLL);
}
...

Saat Anda menyusun dan menautkan aplikasi SampleDLL, sistem operasi Windows mencari DLL SampleDLL di lokasi berikut dalam urutan ini -

  • Folder aplikasi

  • Folder saat ini

  • Folder sistem Windows (File GetSystemDirectory fungsi mengembalikan jalur folder sistem Windows).

  • Folder Windows (File GetWindowsDirectory fungsi mengembalikan jalur folder Windows).