PDA

View Full Version : چگونگی فراخوانی تابعهای دورن یک DLL



Moharram
یک شنبه 18 آذر 1386, 16:56 عصر
سلام

برای فراخوانی تابعهای یک DLL دو روش وجود داره (استاتیک - دینامیک)

1- اگه فایل dll و lib کنار هم موجود باشند در برنامه کنسولی فایل lib رو به فایلهای پروژه Add میکنیم و توابع رو صدا میزنیم ولی اگه برنامه دیالوگی باشه نمیدونم چرا این روش کار نمیکنه.

2- اگه فقط فایل DLL رو داشته باشیم میشه با استفاده از کدهای زیر تابع را صدا زد:
فرض میکنیم تابع بشکل ()void fnMyDLL باشه...



HINSTANCE hDLL = LoadLibrary("myDLL.DLL");
if(hDLL==NULL) AfxMessageBox("Cannot Load Library");

FARPROC fp = GetProcAddress(hDLL,"fnMyDLL");
if(fp==NULL) AfxMessageBox("Cannot find function");

int x=fp();


در موردی که مثل بالا تابع پارامتر نداشته باشه مشکلی نیست و تابع اجرا میشه ولی اگه تابع بخواد یه پارامتر داشته باشه باید همانطور که در MSDN آمده بجای قسمت fp اینجوری عمل کنیم:
در این مورد فرض میکنیم تابع یک مقدار int میگیره و یک مقدار int برمیگردونه...



typedef int (CALLBACK* fnMyDll_Type)(int);

fnMyDll_Type fnMyDll_ptr
fnMyDll_Ptr = (fnMyDll_Type)GetProcAddress(hDLL,"fnMyDLL");
if(fnMyDll_Ptr == NULL) AfxMessageBox("Cannot Find Function");
int x = fnMyDll_ptr(10);


تا اینجای کار تابع اجرا میشه، حتی وقتی با اسمبلی دیباگ میکنیم مقدار درستی برمیگردونه ولی یک Error در مورد Stack میده ...

sasan_vm
یک شنبه 18 آذر 1386, 17:11 عصر
سلام
اگر شما فایل Header File, DLL مربوط به Function prototype ها را داشته باشید دیگر مشکلی در call کردن توابع ندارید. با هر ابزار Import Library می توانید فایل lib را از dll استخراج کنید و بقیه آن...


برنامه دیالوگی باشه نمیدونم چرا این روش کار نمیکنه.


بعید میدونم این ربطی به نوع پروژه داشته باشه، DLL ها براحتی در هر نوع پروژه Win32 (Consol, GUI) استفاده می شوند.
از چه Compiler ای استفاده میکنید ؟

anubis_ir
یک شنبه 18 آذر 1386, 17:17 عصر
CALLBACK باید توسط برنامه اصلی فراخوانی بشه. شما بدنه آنرا باید پیاده سازی کنید.
یعنی زمانیکه CALLBACK را برنامه اصلی صدا می‌زند، مقدار int را برای شما ارسال می‌کند.

Nima_NF
یک شنبه 18 آذر 1386, 18:36 عصر
اگه فایل dll و lib کنار هم موجود باشند در برنامه کنسولی فایل lib رو به فایلهای پروژه Add میکنیمجهت تذکر ، فایل lib را به پروژه اضافه نمی کنیم ، بلکه با توجه به کامپایلر:

1) از طریق option کامپایلر یا جای دیگر باید فلدر و یا فایل lib را به همراه header فایل آن مثل سایر dll های اصلی به برنامه اضافه کنید (نه از طریق add داخل فایل پروژه)

2) نام فایل lib شما را باید از طریق linker بخش properties به پروژه اضافه کنید.

3) header فایل dll شما که با پسوند .h است را باید در بالای برنامه include کنید.
برای تست ، اگر این سه مورد را درست انجام دادید ، هر جای برنامه که توابع را نوشتید باید بتوانید از طریق آن به تعاریف تابع دسترسی داشته باشد و بتوانید آرگومان های آن را نیز مشاهده کنید.

ضمنا گهگاهی خود کامپایلر ها کار بهینه سازی انجام می دهند و نام توابع برای روش دوم استفاده از Dll تغییر می کند که برای مشاهده نام از برنامه dependency walker مایکروسافت می توانید استفاده کنید.

Moharram
شنبه 24 آذر 1386, 18:14 عصر
با تشکر از توجهی که نشون دادید، به این صورت جواب گرفتم:

1- در موردیکه فایل dll و lib را داشته باشیم بعد از اضافه کردن فایل lib به پروژه باید توابع اون را declare کنیم. به اینصورت:



__declspec(dllimport) int fnMyDLL(int)


بعد میشه از تابع استفاده کرد. یه نکته اینکه اگه موقع کامپایل فایل lib موجود نباشه با یک خطا بصورت زیر روبرو میشویم:



Unresolved External symbol ...


ولی اگه dll گم بشه برنامه بدون خطا اجرا میشه و یه پیِغام سیستمی مبنی بر وجود نداشتن dll داده میشه.

2- ولی اگه فقط فایل dll رو داشته باشیم و بخواهیم بصورت dynamic از توابع dll استفاده کنیم، همان روش که در پست قبلی گفتم درسته فقط نباید از CALLBACK استفاده کنیم



typedef int (*fnMyDll_Type)(int);

fnMyDll_Type fnMyDll_ptr
fnMyDll_Ptr = (fnMyDll_Type)GetProcAddress(hDLL,"fnMyDLL");
if(fnMyDll_Ptr == NULL) AfxMessageBox("Cannot Find Function");
int x = fnMyDll_ptr(10);

Nima_NF
شنبه 24 آذر 1386, 20:43 عصر
در موردیکه فایل dll و lib را داشته باشیم بعد از اضافه کردن فایل lib به پروژه باید توابع اون را declare کنیم
اگر Dll را خودتان نوشتید نیازی به دوباره نویسی نیست ، از روش زیر که رایج است می توانید استفاده کنید و سپس همانطور که گفتم هدر فیل dll را به بالای صفحه کدها اضافه کنید ، البته هر گاه می خواهید تعریف و کامپایل کنید ابتدا باید DLL_EXPORTS را یا هر نام جایگزین آن را define کنید تا export کند ، در صورت استفاده تعریف نشده بماند.



#ifdef DLL_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif

DLL_API int Function(void);

Moharram
یک شنبه 25 آذر 1386, 17:28 عصر
با تشکر از توضیحات دوستان:

Nima_NF
anubis_ir
sasan_vm

مشکل بطور کامل حل شد ...