كيفية القيام بما يلي: تنظيم سلاسل COM بـاستخدام C++ Interop

يوضح هذا الموضوع كيف يمكن تمرير BSTR (تنسيق السلسلة الأساسي المفضل في برمجة COM) من دالة مُدارة إلى غير مدارة ، والعكس بالعكس. للتشغيل التفاعلي مع أنواع السلاسل الأخرى, راجع المواضيع التالية:

أمثلة التعليمات البرمجية التالية تستخدم توجيهات # pragma ـmanaged, unmanaged لتنفذ الدالات المدارة و غير المدارة في نفس الملف , ولكن تتفاعل هذه الدالات بنفس الطريقة في حالة تعريفها في ملفات منفصلة. الملفات التي تحتوي على دالات غير مدارة فقط لا تحتاج إلى أن يتم تحويلها برمجياً باستخدام /clr (التجميع وقت تشغيل اللغة العامة).

مثال

يوضح المثال التالي كيف يمكن تمرير BSTR (تنسيق السلسلة المستخدم في برمجة COM) من دالة مُدارة إلى غير مدارة. يستخدم استدعاء الدالة التي تمت إدارتها StringToBSTRإلى الحصول على الالعنوان من تمثيل BSTR محتويات النظام.سلسلة.NET. Th هو مؤشر هو مثبت باستخدام pin_ptrللتأكد من أن العنوان الفعلي الخاص به هو لا تتغير أثناء دورة تجميع البيانات المهملة بينما يتم تنفيذ دالة غير مدار. يحظر على جامع البيانات المهملة نقل الذاكرة حتى ينتقل pin_ptr خارج النطاق.

// MarshalBSTR1.cpp
// compile with: /clr
#define WINVER 0x0502
#define _AFXDLL
#include <afxwin.h>

#include <iostream>
using namespace std;

using namespace System;
using namespace System::Runtime::InteropServices;

#pragma unmanaged

void NativeTakesAString(BSTR bstr) {
   printf_s("%S", bstr);
}

#pragma managed

int main() {
   String^ s = "test string";

   IntPtr ip = Marshal::StringToBSTR(s);
   BSTR bs = static_cast<BSTR>(ip.ToPointer());
   pin_ptr<BSTR> b = &bs;

   NativeTakesAString( bs );
   Marshal::FreeBSTR(ip);
}

يوضح المثال التالي كيف يمكن تمرير BSTR من دالة غير مدارة إلى مدارة. الدالة المدارة المتلقية يمكنها استخدام السلسلة في BSTR أو استخدام PtrToStringBSTR لتحويله إلى String للاستخدام مع الدالات الأخرى المدارة. لأن الذاكرة التى تمثل BSTR مخصصة في كومة الذاكرة المؤقتة غير المدارة، لا تثبيت ضروري لأنه لا يوجد جمع للبيانات المهملة في كومة الذاكرة المؤقتة غير المدارة.

// MarshalBSTR2.cpp
// compile with: /clr
#define WINVER 0x0502
#define _AFXDLL
#include <afxwin.h>

#include <iostream>
using namespace std;

using namespace System;
using namespace System::Runtime::InteropServices;

#pragma managed

void ManagedTakesAString(BSTR bstr) {
   String^ s = Marshal::PtrToStringBSTR(static_cast<IntPtr>(bstr));
   Console::WriteLine("(managed) convered BSTR to String: '{0}'", s);
}

#pragma unmanaged

void UnManagedFunc() {
   BSTR bs = SysAllocString(L"test string");
   printf_s("(unmanaged) passing BSTR to managed func...\n");
   ManagedTakesAString(bs);
}

#pragma managed

int main() {
   UnManagedFunc();
}

راجع أيضًا:

المرجع

استخدام PInvoke) C++ Interop الضمني )