19 Aralık 2018 Çarşamba

Windows'ta DLL Geliştirmek

Giriş
DLL'den metod export etmek için
1. GetProcAddress metodu ile yüklenen metodların bulunması ya
2..def dosyasında tanımlı olması ya da
3.şu şekilde tanımlı
extern "C" __declspec(dllexport) ...
olarak tanımlı olması gerekir. Bu yöntemi kullanıyorsak dll projesinin. lib çıktısı ile ana projeyi linkleriz.

1..def dosyası
.def dosyaları çok eski bir yöntem ve artık kullanılmamalı.

2. extern "C" __declspec(dllexport)
__declspec(dllexport) kelimelerinden sonra calling convention'ı belirlemek gerekir. Bu kelimeler metodun PE export tablosuna eklenmesini sağlar.

1.C calling convention'da (__cdecl) çağıran metod stack'i temizler. __cdecl Calling Convention yazısına bakabilirsiniz.

2. Windows calling convention'da (__stdcall) çağrılan metod stack'i temizler.

Örnek - Belirtilmemiş
Windows DLL metodları otomatik olarak "__stdcall convention"'ı uygular. Şöyle yaparız.
extern "C" __declspec(dllexport) void foo(void* v) { int a = 0; }
Daha sonra .lib ile linkelemediysek şöyle çağırırız.
foo f = (foo)GetProcAddress(hmod, "foo");
foo kendi içinde başka metodları kullanabilir.
extern "C" __declspec(dllexport) foo()
{
  int result = Bar();
}
Örnek
Şöyle yaparız.
extern "C" __declspec(dllexport) int validate( int v_mode, char * data, int data_length );
Örnek - __cdecl
Şöyle yaparız. Burada calling convention olarak __cdecl kullanılıyor.
extern "C" __declspec(dllexport) int __cdecl test();
Örnek - __stdcall
Şöyle yaparız.
#ifdef PROJET_EXPORTS
#  define EXPORT __declspec(dllexport)
#else
#  define EXPORT __declspec(dllimport)
#endif

#define CALLCONV_API __stdcall

#ifdef __cplusplus
extern "C" // C wrapper
{
#endif

    EXPORT void CALLCONV_API foo(void);
#ifdef __cplusplus
}
#endif
Örnek
Export edilen metod C çağrısı olduğu için imzasında C++ tipleri kullanılamaz. Açıklaması şöyle.
When you write an exported DLL function, you SHOULD NOT use any C++ library types in its interface, as these are compiler, version, and even solution (DEBUG or NDEBUG) dependent.

If you do, you must make sure that the caller uses the same implemetation of those types.

You should restrict DLL exported functions to use only types in their interface that are compatible with C types, or other mutually agreed upon types.

Inside your DLL implementation, you can do whatever you want!
Şu kod std::wstring kullandığı için yanlış. Başka bir derleyici bu DLL'i kullanamayabilir.
extern "C" __declspec(dllexport) void Msg(std::wstring filename)
{   
  ...
}
string
DLL'e unicode string parametre geçmek istersek LCWSTR/LPWSTR yani const wchar_t * kullanılabilir.

Hiç yorum yok:

Yorum Gönder