PDA

View Full Version : سوال: استفاده از فایل TLB در MFC project



Hamid.Mayeli
چهارشنبه 03 آذر 1389, 11:00 صبح
سلام

من برنامه نویس C# هستم و لازم دارم یه DLL که ComVisible هست رو در C++ استفاده کنم از DLLم یه فایل TLB ساختم ولی نمی دونم چطوری باید از اون تو C++ استفاده کنم.
:افسرده:

با تشکر

mehdi.mousavi
پنج شنبه 04 آذر 1389, 17:15 عصر
سلام من برنامه نویس C#‎‎ هستم و لازم دارم یه DLL که ComVisible هست رو در C++‎‎ استفاده کنم از DLLم یه فایل TLB ساختم ولی نمی دونم چطوری باید از اون تو C++‎‎ استفاده کنم. با تشکر

سلام.
فرض میکنم که شما با اصول ابتدایی COM آشنا هستید در نتیجه در مورد Marshaling، Apartments و ... صحبت نمیکنم و فقط به سوالی که پرسیده اید پاسخ میدم.

ابتدا مطمئن بشید که به Interface ها و کلاسهایی که در C#‎ تعریف کرده اید و قصد دارید اونها رو از طریق COM Interop استفاده کنید، GUID های مناسبی Assign کرده باشید. برای ایجاد GUID، از منوی Tools در Visual Studio گزینه Create GUID رو انتخاب کنید (یا از شاخه ای که Visual Studio رو در اون نصب کرده اید، شاخه Common7\Tools رو انتخاب کرده و برنامه ای تحت عنوان guidgen.exe رو اجرا کنید).

گزینه پنجم رو در برنامه مربوطه (پس از اجرا) انتخاب کرده و کلید Copy رو بزنید. حالا GUID ایجاد شده رو به Interface مربوطه با استفاده از GuidAttribute اختصاص بدید. سپس GUID جدیدی تولید کنید (به روش مشابه) و اونو به Class مورد نظر Apply کنید. به همین ترتیب اینکارو برای کلیه Class ها و Interface های موجود در برنامه C#‎ اتون انجام بدید.

سپس ComVisible و InterfaceType رو برای Interface خودتون true کنید (اگر اینکارو نکرده اید). اگر نیاز هستش، Assembly مورد نظر رو CLSCompliant نیز مارک کنید...

وقتی پروژه C#‎ خودتون رو ساختید، به Visual Studio Command Prompt برید تا به Environment Variable و در نتیجه Utility ای تحت عنوان regasm دسترسی داشته باشید. شاخه جاری رو به شاخه Debug یا Release پروژه Managed خودتون تغییر بدید و اونجا، کنار DLL ای که ایجاد کرده اید، دستور زیر رو بزنید:


regasm mylib.dll /tlbبا اینکار یه فایل tlb در همون مسیر ایجاد میشه و فایل مزبور نیز Register میشه در نتیجه، Entry های لازم برای CreateInstance کردن Object های مورد نظر در Registry قرار می گیره. سپس پروژه MFC خودتون رو باز کنید و خطوط زیر رو در بالای فایل C++‎ (یا stdafx.h، یا ...) قرار بدید:

#import "mylib.tlb" raw_interfaces_only named_guids
using namespace MyLib;

دقت کنید که MyLib در واقع namespace ای هستش که شما سمت پروژه Managed اتون کلاسها و Interface مورد نظر رو تحت اون تعریف کرده اید. اگر لازم بود، می تونید mscorlib.tlb رو نیز import کنید. فایل mscorlib.tlb نیز Type Library اسمبلی mscorlib هستش.

در هر حال، کد فوق، باعث ایجاد یک فایل tlh در کنار پروژه شما میشه، که تعاریف مربوط به کلاس و Interface های Managed شما، پس از تبدیل به کدهای معادل COM Compliant، قابل مشاهده هستش. سپس، اونجاییکه قصد دارید تا از کلاس مورد نظر استفاده کنید، ابتدا یکبار و فقط یکبار، کد زیر رو بنویسید:

HRESULT hr = CoInitialize(NULL);
if(hr != S_OK)
return FALSE;

return TRUE;


این کار باعث میشه تا Thread شما در STA Apartment قرار بگیره، در نتیجه، از این پس میتونید در اون Thread با از COM Server های مورد نظر استفاده کنید و Object های مورد نظرتون رو بسازید. دقت کنید که در انتهای کار، بعد از اینکه کلیه Reference ها به COM Object های خودتون رو آزاد کردید و دیگه کاری در اون Thread با COM Object ها نداشتید، حتما CoUninitialize رو فراخوانی کنید.

سپس با استفاده از کد زیر (که میشه به N طریق دیگه هم نوشتش، اما این روشی هستش که من اونو می پسندم)، یه Smart Pointer به Interface مورد نظر تعریف کنید:

CComPtr<IPerson> spPerson = NULL;

اینجا فرض کردم IPerson رو شما در Managed Code اتون تعریف کرده اید... دقت کنید که استفاده از Smart Pointer ها باعث میشه تا دیگه شما نگران آزاد کردن حافظه نباشید. هر وقت متغیر فوق از Scope خارج بشه، خودش بطور خودکار Destroy میشه، ضمن اینکه عمل Reference Counting نیز بطور خودکار انجام خواهد شد. سپس، با استفاده از کد زیر، CLSID ی مورد نظر رو می تونید Create کنید:

HRESULT hr = CoCreateInstance(CLSID_Person, NULL, CLSCTX_INPROC_SERVER, IID__Person, reinterpret_cast<void**>(&spPerson));
if(hr != S_OK)
return FALSE;

اینجا، من فرض کردم که CLSID_Person در Type Library ایجاد شده وجود داره، و با استفاده از IID__Person یه Instance از اون Class ایجاد کردم. از اینجا به بعد می تونید روی spPerson متودهایی که روی اون Interface تعریف کرده بودید و در کلاس مورد نظر پیاده سازی کرده بودید رو فراخوانی کنید.

از اینجا به بعد (یا حتی قبلش) ممکنه با مشکلات عجیب و غریبی روبرو بشید که حل اونها مستلزم داشتن اطلاعات کاملی در مورد COM، Data Marshaling، Calling Convention و ... هستش.

موفق باشید.