PDA

View Full Version : مقاله: ساخت یه API ویندوزی به زبان c++ و استفاده از آن در C#



mosini
شنبه 02 خرداد 1388, 11:36 صبح
سلام
در این مقاله سعی میکنم خیلی ساده طریقه ساخت API های ویندوز رو شرح بدم.البته برای سادگی ساخت این گونه API ها از نرم افزار Visual Studio استفاده کردم.می خوام یهAPI ای بسازم که شامل تابعی هست که دو عدد صحیح را بعنوان ورودی میگیره و نتیجه ی جمع این دو عدد را بعنوان خروجی میگیره.
خب برای این کار Visual Studio 2008 خودتون رو اجرا کنید و به مسیر زیر بروید:
File->New->Project
سپس زبان Visual C++ را انتخاب کنید و قالب برنامه نویسی را Win32Project را انتخاب کنید.نامی برای آن برگزینید.مثلا myDll و سپس روی OK کلیک کنید.با کلیک بر روی OK پنجره خوشامد گویی باز میشود بر روی next کلیک کنید.سپس از قسمت application type گزینه ی DLL را انتخاب و بر روی Finish کلیک کنید.
نکته:قالب برنامه نویسی را به این دلیل Win32Project انتخاب کردیم، چون API های ویندوز نیز از همین نوع هستند.
پس از کلیک بر روی finish پنجره ای حاوی کد برای فایل کد myDll.cpp به شما نشان داده میشود.
نکته:در صورتی که برای شما این فایل کد نشان داده نشد بر روی solution explorer رفته و از پوشه source بر روی myDll.cpp دو بار کلیک کنید.
همانطور که در این فایل کد میبینید ابتدا یه هدر(header) بنام include# stdafx در آن وجود دارد.
نکته:کلا برنامه های ++C با هدر های اینگونه ای شروع می شوند.
در ادامه می خواهیم api های خودمون رو بسازیم بطوریکه:
این dll یا api بتونه توی هر زبان برنامه نویسی دیگه ای مورد استفاده قرار بگیره.
در این صورت باید در ادامه تابع مورد نظرمون را تعریف کنیم.چون این تابع باید بتونه تو هر زبان برنامه نویسی دیگه ای مورد استفاده قرار بگیره باید عبارت زیر را قبل از نوشتن تابع بنویسیم:

__declspec(dllexport)

و بعد از این عبارت باید پیاده سازی تابع خودمون رو بنویسیم.پس مینویسیم:

__declspec(dllexport) int Sum(int num1,int num2)
{
return num1+num2;
}

حال کاری که می ماند این است که صریحا اعلان کنیم که این تابع باید توسط محیط خارج از خودش قابل دسترسی باشد.برای این کار بر روی نام پروژه در solution explorer راست کلیک کنید و سپس از روی Add گزینه ی New Item را کلیک کنید و از پنچره ای که باز میشه آیتم ای بنام Module-Definition file را از ساختار درختی سمت چپ این پنجره بنام Code انتخاب کنید و نام آنرا مثلا بگذارید export.و بر روی OK کلیک کنید.همونطور که میبینید فایلی بنام export.def برای شما ظاهر میشود وشما باید در این فایل بگید که کدام تابع ها در برنامتون باید از خارج از این برنامه قابل دستیابی باشند.ما در این مثال می خواهیم که تابع sum قابل دستیابی باشه پس زیر عبارت LIBRARY "myDll" مینویسیم:EXPORT Sum .
نکته:باید کلمه EXPORT با حروف بزرگ بنویسید .
در ادامه solution خود را build کنید و دیگه کار تمومه.در ادامه نحوه استفاده از این API را در C# سی شارپ توضیح خواهم داد.
موفق باشید

mosini
شنبه 02 خرداد 1388, 12:39 عصر
خوشحال میشم دوستان نظرشون رو در مورد کیفیت این مقاله بگویند.

razavi_university
شنبه 02 خرداد 1388, 13:50 عصر
ممنون از مقاله ای که نوشتید، بهتره کل پروژه رو هم ضمیمه کنید



__declspec(dllexport)

یعنی چی ؟ و برای چه 2 بار قبل از تعریف تابع میاد؟

Unknownlive
شنبه 02 خرداد 1388, 13:57 عصر
نظرم اینه که عالی بود خیلی وقت بود که کسی اموزشی نداده بود و همه سوال می کردند

mosini
دوشنبه 04 خرداد 1388, 08:15 صبح
دوست عزیز آقای razavi
__declspec دو بار نمی آد.من خواستم در بار اول در موردش توضیح بدم برای همین آوردمش.وگرنه شما باید برای هر تابعی که می خواهید اونو تعیریف کنید یه دونه __decspec بنویسین.
موفق باشید

Armin060
دوشنبه 04 خرداد 1388, 13:22 عصر
چيز جالبی‌ گفتيد، ممنون:چشمک:.
اگر ميشه نحوه استفاده رو هم بگيد.:چشمک:

mosini
سه شنبه 05 خرداد 1388, 09:44 صبح
چيز جالبی‌ گفتيد، ممنون:چشمک:.
اگر ميشه نحوه استفاده رو هم بگيد.:چشمک:

ممنون از همه
در مورد نحوه استفاده از این dll:
همونطور که میدونید این dll ای که ما ساختیم شامل کد مدیریت نشده یا unmanaged هست.و برای استفاده از اون در برنامه سی شارپ که شامل کد managed یا مدیریت شده است ، باید از attribute ای بنام DLLImport برای شناسوندن این dll به برناممون استفاده کنیم.کاری که DLLImport میکنه اینه که میاد کد های درون dll رو به کد مدیریت یافته معادلش تبدیل میکنه تا این کد درون dll توانایی مورد استفاده قرار گرفتن در زبان های managed مثل سی شارپ رو داشته باشه.
خب در ادامه به نحوه انجام این کار می پردازیم:
برای استفاده از تابع Sum در dllای که ساختیم در زبان سی شارپ باید ابتدا مثل قدیم اول visual studio خودمون رو اجرا کنیم و از منوی file سپس new و بعد project را انتخاب کنیم.قالب برنامه نویسیتون رو console application انتخب کنید.و نام اونو مثلا بگذارید DllUser.

در ادامه داخل کلاس program ،خارج از متد های دیگر باید متدی بنویسید که از نظر signature یا همون ورودی و خروجی متد همانند signature تابعی باشد که درون dll تون هست و می خواهید اینجا ازش استفاده کنید.
کلا کاری که باید انجام دهید اینه که یه واسطی برای تابع Sum در dll ، توی برنامه سی شارپ خودمون بسازیم و این واسط باید فقط نام تابع Sum را داشته باشه و پارامتر های ورودی و خروجیش با تابع sum اِ داخل dll,مون یکی باشه.حالا در ادامه کد اونو میارم تا بهتر درک کنیم:

class Program
{
static void Main(string[] args)
{
int result = Sum(2,4);
Console.WriteLine(result);
}

[System.Runtime.InteropServices.DllImport(@"C:\myDll.dll")]
public static extern int Sum(int num1,int num2);
}


خب همونطور که میبینید DllImport درون فضای نام System.Runtime.InteropService هست.اصلا از نام interopService میتونیم دریابیم که عناصر درون اون با منابع خارج از .net کار خواهند کرد.
نکته:باید به اون دسته از عزیزانی که فکر میکنند میشه با رفتن در solution explorer و کلیک بر روی references و add کردن از قسمت browse این dll رو add یا اضافه کردن ، بگم که شما از این روش تنها می توانید برای اضافه کردن dll های نوشته شده در دات نت یا کلی تر بگم dll های شامل کد مدیریت یافته یا همون managed code استفاده کنید.
تعریف:
بهتره در اینجا یه تعریفی در مورد کد مدیریت یافته و مدیریت نیافته بدم.ببینید هر کدی که مستقیما به منابع سیستمی دسترسی نداشته باشه(منابع سیستمی مثل حافظه اصلی) و نتونه مستقیما اون منابع را دستکاری کنه و تنها قادر باشه به صورت غیر مستقیم و به شکلی امن این کار ها رو انجام بده می گیم کدمون یه کد مدیریت یافته هست.زبانی مثل سی شارپ در اصل و ذات خودش از کد های مدیریت یافته استفاده میکنه اما خوب این امکان براتون گذاشته شده تا اصل و ذاتش رو بهم بزنید! و از کد مدیریت نشده هم در اون استفاده کنید(این کار رو با کلمه کلید unsafe انجام میدن..امیدوارم بتونم مقاله ای در این رابطه براتون بزارم).کد های مدیریت نشده (مثلا کدی که ما توی زبان c++ مینوشتیم) دسترسی مستقیم به منابع را میده، البته بصورت غیر امن(ممکنه براتون این سوال پیش بیاد که امن یا غیر امن چه مفهومی داره؟خوب خیلی ساده کد امن یعنی کدی که دیگه نباید نگران رها سازی منابعی باشی که ازشون تو برنامت استفاده کردی و این مکانیزم رو دات نت پایه گذاری کرده به توسط ابزار(برنامه ای) بنام GC یا Garbage Collection.)خب دیگه داریم از بحث پرت میشیم.بدیه علم کامپیوتری ،البته نمیشه بگی بدی اما هر چی که هست تا می خواهی یه چیزی رو کامل توضیح بدی مجبوری از چندین منبع سخن برانی.برگردیم بر سر موضوع خودمون.

در درون DllImport من نام اون dll ای که ساخته بودم آوردم.فرض کنید اون dll توی درایو c من بوده.پس اگه شما dllتون جای دیگس مسیر اون جا رو بدید.یا میتونید اون dll رو کپی کنید و در درایو C بزارید و از همین کدی که من نوشتم استفاده کنید!
خب مطلبی که باید همیشه به اون توجه زیادی بکنیم اینه که بعد از نوشتن dllimport در زیر این باید به برنامه سی شارپ خودمون بگیم که توی این dll ای که می خواهیم به برنامه اضافه بشه ، از کدام عناصر درونش می خواهیم استفاده کنیم؟
من دراین جا می خوام از تابع Sum که درون myDll هست استفاده کنم.برای همین باید اینو به سی شارپ معرفی کنم.حالا چه جوری؟
همونطور که از کد میبینید باید همیشه و همیشه از public static extern بعنوان سر آغاز معرفی عنصرتون استفاده کنید.حالا چرا extern؟ چون extern به معنای بیرونی است و بدیهیه که myDll که شامل Sum از اجنبی هاست(بیرونی هست)!
و در ادامه باید دقیقا signature تابع sum را اینجا بنویسید.باید نام تابع sum را دقیقا از نظر بزرگ و کوچکی حروف اون در myDll اینجا هم عینا بنویسید.

بعد از تکمیل این قسمت میتونید از sum که توی myDll هست و کدش به زبان Visual C++ نوشته شده براحتی همانند استفاده از یک متد نوشته شده درون برنامه سی شارپ مون استفاده کنیم.همونطور که میبینید در متد Main برنامه، Sum را فراخوانی کردیم.
توضیح:
با فراخوانی Sum در حقیقت محیط runtime درون CLR که وظیفه اجرای برنامه رو داره میره و کد Sum درون myDll را پیدا میکنه و بعدش اونو بصورت کد مدیریت یافته از نو بازنویسی میکنه و در واقع این کد مدیریت یافته ساخته شده توسط CLR را برای شما اجرا میکنه.این هم نکته ای بود که فکر کنم بد نیست بدونید.
اگه مقاله جایی توضیح بیشتر می خواد، لطف کنید آگاهم کنید.
موفق باشید.
naeimabadi.Blogfa.com