AmenoTejikara
دسترسی به کدهای سی++ در زبان های مدیریت شده توسط P/Invoke
مدت ها بود که موضوع مناسبی به ذهنم نمیرسید تا در موردش بنویسم، تا اینکه همین الان بصورت اتفاقی P/Invoke یادم افتاد. برای من که مسئله جالبی هستش، گفتم بنویسم شاید بدرد شما هم خورد?
طبق تعریفی که خود مایکروسافت ارائه میکنه، P/Invoke یه تکنولوژی هستش که به ما اجازه میده به تابع ها(functions) ، ساختارها(structs) و کالبک ها(callbacks) تو کدهای مدیریت نشده سی++ دسترسی داشته باشیم!
به عبارت ساده تر ما میتونیم از کتابخونه های سی++، یا کتابخونه های خود ویندوز توی زبان های برنامه نویسی مثل سی شارپ C# استفاده کنیم.
اگر باز هم متوجه قضیه نشدید بزارید بیشتر توضیح بدم:
خود ویندوزی که دارید ازش استفاده میکنید برای انجام دادن فعالیت ها، کدهاش رو داخل کتابخونه هایی با پسوند dll قرار داده و چون این کتابخونه ها اکثرا با سی++ نوشته شدن بصورت کدهای مدیریت نشده هستن (حالا با اینش کار نداریم) ما میتونیم کارهایی که ویندوز انجام میده رو با سی شارپ یا زبون های دیگه انجامش بدیم، مثلا گرفتن اسم پنجره ها، مخفی کردن پنجره ها، تغییرات توی taskbar و هزار جور کار دیگه اینجاس که بحث p/invoke میاد وسط، پی اینووک مثل یه پل ارتباطی میمونه که میاد امکان دسترسی به این کدها رو برای ما فراهم میکنه/ در ادامه میخوام نحوه استفاده از p/invoke رو اموزش بدم ولی قبلش میخوام بهتون آموزش بدم که برنامه نویس های سی++ چطوری این امکان رو فراهم میکنن?
برای این کار یه پروژه خالی سی++ ایجاد کنید (خروجی پروژه باید یه dynamic library dll باشه) حالا از هر محیطی خواستید استفاده کنید مهم نیست مهم اینه که خروجی شما فایل dll باشه
پوشه ها و فایل های ایجاد شده رو حذف کنید و خودتون یه فایل cpp ایجاد کنید.
داخل این فایل یه متد مینویسیم که برای ما متن سلام رو چاپ کنه:
#include <iostream>
void WriteHello()
{
std::cout << "Hello"
}
من میخوام کاری کنم که یه برنامه نویس تو زبان سی شارپ بتونه این متد رو فراخوانی کنه و ازش استفاده کنه پس کد زیر رو باید بنویسیم:
extern "C" __declspec(dllexport) void WriteHello();
نکته مهم اینکه نوع بازگشتی تابع و اسم تابع باید دقیقا در عبارت بالا نوشته بشه که توی مثال ما نوع بازگشتی تابع void و اسم تابع WriteHello بود.
کافیه پروژه رو کامپایل کنیم و فایل dll رو کپی کنیم کنار فایل Exe که قرار هست با سی شارپ بنویسیم?
حالا که فایل dll رو اماده کردیم یه پروژه با سی شارپ ایجاد کنید (از نوع کنسول ایجاد کنید تا عملکرد برنامه قابل مشاهده باشه چون قراره یه متنی رو cout کنه تو کنسول چاپ میشه)
اول باید فایل dll رو معرفی کنیم:
[DllImport("mylibrary.dll")]
بعد باید تابعی که میخوایم ازش استفاده کنیم رو اسمش رو بنویسیم (حتما باید زیر عبارت بالا بنویسیم وگرنه خطا میگیریم):
public static extern void WriteHello();
اینجا هم باید حواسمون باشه که اسم تابع و نوع بازگشتی رو دقیق بنویسیم، حالا اگر تابع WriteHello(); رو هرجا که بخوایم بنویسیم کدهایی که تو سی++ داخل متد نوشته شده اجرا میشه?
به این مراحلی که انجام دادیم P/Invoke میگویند?
البته باید دقت کرد اگر تابع پارامتر ورودی یا متغیر بازگشتی داشت نوعشون باید به درستی انتخاب بشه چون برخی از نوع های متغیرها توی کدهای مدیریت نشده و مدیریت شده فرق داره مثل string که توی سی شارپ string هست ولی توی سی++ فرق میکنه مایکروسافت لیستی از این نوع هارو داخل جدولی اینجا ارائه کرده که میتونید مطالعه کنید.
در اخر شاید این مثال رو که تایتل پنجره فعال تو ویندوز رو میگیره و توی مسیج باکس نشون میده رو بهتر درک کنید:
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
private string GetActiveWindowTitle()
{
const int nChars = 256;
StringBuilder Buff = new StringBuilder(nChars);
IntPtr handle = GetForegroundWindow();
if (GetWindowText(handle, Buff, nChars) > 0)
{
return Buff.ToString();
}
return null;
}
MessageBox.Show(GetActiveWindowTitle());
اینجا از 2 تا تابع استفاده شده یکی GetForegroundWindow که میاد پنجره ای که بالاتر از همه پنجره ها هست (اونی که فعاله و فوکوس روشه) رو انتخاب میکنه و GetWindowText تایتل اون پنجره رو دریافت میکنه/
در پایان اگر براتون سواله این توابع رو از کجا میشه پیدا کرد، باید بگم که با رفتن به این سایت میتونید به تمام اطلاعات کافی در مورد کتابخونه های ویندوز دسترسی داشته باشید.
مطلبی دیگر از این انتشارات
دانشگاه vs بازار کار
مطلبی دیگر از این انتشارات
HTML زبان برنامه نویسی نیست!!!!
مطلبی دیگر از این انتشارات
بهترین فریمورک برای برنامهنویسی؟