如何:使用 C++ 互操作封送 ANSI 字符串

本主题演示如何使用 C++ 互操作传递 ANSI 字符串,但.NET Framework String 表示 Unicode 格式的字符串,因此转换为 ANSI 是一个额外的步骤。 若要与其他字符串类型进行互操作,请参阅以下主题:

以下代码示例使用 managed 和 unmanaged #pragma 指令在同一文件中实现托管和非托管函数,但如果这些函数在单独的文件中定义,则将以相同方式进行交互。 由于仅包含非托管函数的文件不需要使用 /clr(公共语言运行时编译)进行编译,因此它们可以保留其性能特征。

示例:传递 ANSI 字符串

该示例演示如何使用 StringToHGlobalAnsi 将 ANSI 字符串从托管函数传递到非托管函数。 此方法在非托管堆上分配内存,并在执行转换后返回地址。 这意味着不需要固定(因为 GC 堆上的内存不会传递到非托管函数),并且必须显式释放从 StringToHGlobalAnsi 中返回的 IntPtr 或意味着内存泄漏结果。

// MarshalANSI1.cpp
// compile with: /clr
#include <iostream>
#include <stdio.h>

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

#pragma unmanaged

void NativeTakesAString(const char* p) {
   printf_s("(native) received '%s'\n", p);
}

#pragma managed

int main() {
   String^ s = gcnew String("sample string");
   IntPtr ip = Marshal::StringToHGlobalAnsi(s);
   const char* str = static_cast<const char*>(ip.ToPointer());

   Console::WriteLine("(managed) passing string...");
   NativeTakesAString( str );

   Marshal::FreeHGlobal( ip );
}

示例:访问 ANSI 字符串所需的数据封送

以下示例演示了访问由非托管函数调用的托管函数中的 ANSI 字符串所需的数据封送。 接收本机字符串时,托管函数可以直接使用此字符串,也可以使用 PtrToStringAnsi 方法将其转换为托管字符串,如下所示。

// MarshalANSI2.cpp
// compile with: /clr
#include <iostream>
#include <vcclr.h>

using namespace std;

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

#pragma managed

void ManagedStringFunc(char* s) {
   String^ ms = Marshal::PtrToStringAnsi(static_cast<IntPtr>(s));
   Console::WriteLine("(managed): received '{0}'", ms);
}

#pragma unmanaged

void NativeProvidesAString() {
   cout << "(native) calling managed func...\n";
   ManagedStringFunc("test string");
}

#pragma managed

int main() {
   NativeProvidesAString();
}

另请参阅

使用 C++ 互操作(隐式 PInvoke)