C++/CLI的用途
作为一个有着正常审美观的人,我简直无法忍受 C++/CLI(以及 managed c++)的丑陋。不过,近来发现,这个丑东西也还有点用,在把原生开发接口包装成托管开发接口时,比 C# 的互操作容易的多(互操作看了看,头大呀)。磕磕绊绊几天,终于把一个 SDK 开发包转换完成了。总结经验如下:
对于 clr 中的引用类型,定义变量时要用个
^符,如String^ var1、array<int>^ var2、array<String^>^ strarr等,值类型不用。一个类型是值类型还是引用类型,取决于定义时用的是value struct/class还是ref struct/class。定义枚举要用
enum struct/class,否则是个原生枚举,C# 里不能用。可指定数值类型和flags属性,如下:
[FlagsAttribute]
public enum class TestEnum : unsigned int
{
flag1 = 0x00000001,
flag2 = 0x00000002,
};
- 原生字符串转换为托管字符串时,用:
char* s1 = "native string1";
wchar_t* s2 = L"native string2";
String^ str1 = gcnew String( s1 );
String^ str2 = gcnew String( s2 );
托管字符串转换为原生字符串时,用:
pin_ptr<const wchar_t> p = PtrToStringChars( str );
如果需要 ANSI 字符集,可再对 p 进行一些常规字符集转换。
- 指针、句柄等与 0 进行赋值比较等操作时用
nullptr,而不是NULL或 0,后者会导致装箱等操作,如:
HANDLE h = nullptr;
if( h == nullptr ){}
- C# 中定义函数参数时的
ref关键字在 C++/CLI 中用%号对应,如:
void foo( String^% refstr );
out 关键字,需要用 [System::Runtime::InteropServices::OutAttribute] 声明一下。
- 数组空间初始化,用
()而不是[],也就是说它是一个函数调用,如:
array<int>^ arr = gcnew array<int>(100);
的作用是定义一个有 100 个元素的数组。
C++/CLI 中很多地方不能用
const、volatile等关键字,如果编译报错,就把它们去掉吧。尽量不要定义自己的
DllMain,如果必须定义的话,DllMain中不要进行任何托管操作,否则极易导致死锁。可以#pragma managed编译指令,临时打开或关闭托管。暂时没有了,等想起来再补充。
