如何:送使用C++ Interop的COM字符串
此主题演示如何在托管函数和非托管函数之间传递 BSTR(在 COM 编程中非常受欢迎的基本字符串格式)。 有关与其他字符串类型进行交互操作的信息,请参见以下主题:
下面的代码示例使用 managed, unmanaged #pragma 指令在同一个文件中实现托管函数和非托管函数,但如果在不同的文件中定义这些函数,则它们将以同样的方式进行交互操作。 不需要使用 /clr(公共语言运行时编译) 对仅包含非托管函数的文件进行编译。
示例
下面的示例演示如何将 BSTR(COM 编程中使用的一种字符串格式)从托管函数传递到非托管函数。 执行调用的托管函数使用 StringToBSTR 获取 .NET System.String 内容 BSTR 表示形式的地址。 使用 pin_ptr (C++/CLI) 固定此指针,以确保执行该非托管函数时,其物理地址在垃圾回收周期期间不发生更改。 在 pin_ptr (C++/CLI) 超出范围之前,将禁止垃圾回收器移动内存。
// 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();
}