如何在 C++/CLI 中转发声明方法以匹配“C++”的托管扩展的签名引用托管类型的方法
我想从使用 /clr
(C++/CLI) 编译的 C++ 代码调用使用 /clr:oldsyntax
(C++ 语法的托管扩展)编译的方法。但是,我在 C++/CLI 中向前声明该方法以使其与“C++ 托管扩展”签名匹配时遇到问题。
使用“C++ 的托管扩展”的版本中的声明如下所示:
void MangToUnMangDateTime(System::DateTime & managedDT, tm& unmangDT);
注意:第一个参数 (managementDT) 是此问题感兴趣的参数。 这会导致该方法出现以下 msil(已找到)使用 ildasm.exe):
.method assembly static void MangToUnMangDateTime(valuetype [mscorlib]System.DateTime& modopt([mscorlib]System.Runtime.CompilerServices.IsImplicitlyDereferenced) managedDT,
valuetype tm* modopt([mscorlib]System.Runtime.CompilerServices.IsImplicitlyDereferenced) unmangDT) cil managed
第一次尝试:
我第一次尝试在 C++/CLI 中转发声明此方法,结果如下:
void MangToUnMangDateTime2(System::DateTime % managedDT, tm& unmangDT);
结果是以下 msil:
.method assembly static void MangToUnMangDateTime(valuetype [mscorlib]System.DateTime& managedDT,
valuetype tm* modopt([mscorlib]System.Runtime.CompilerServices.IsImplicitlyDereferenced) unmangDT) cil managed
除了“C++ 托管扩展”版本中包含的附加 modopt MSIL 声明符之外,它匹配:
modopt([mscorlib]System.Runtime.CompilerServices.IsImplicitlyDereferenced)
第二次尝试
我第二次尝试在 C++/CLI 中转发声明此方法,如下所示:
MangToUnMangDateTime(System::DateTime & managedDT, tm& unmangDT);
作为旁注,我对在 C++/CLI 中编译的这个方法感到惊讶,因为我预计它希望我在托管上使用 % 语法 这导致了以下 msil:
.method assembly static void MangToUnMangDateTime(valuetype [mscorlib]System.DateTime* modopt([mscorlib]System.Runtime.CompilerServices.IsImplicitlyDereferenced) managedDT,
valuetype tm* modopt([mscorlib]System.Runtime.CompilerServices.IsImplicitlyDereferenced) unmangDT) cil managed
这个与 modopt MSIL 声明符匹配,但它是一个指针 *
而不是引用 &
。
问题:
那么,有没有办法让我在 C++/CLI 中转发声明以匹配“C++ 托管扩展”版本中的签名?也许通过参数上的属性?
约束:我不想修改“C++ 托管扩展”版本。显然,如果我将“C++ 托管扩展”版本修改为按值传递(这可能应该放在第一位):
void MangToUnMangDateTime(System::DateTime managedDT, tm& unmangDT);
那么我可以通过在 C++/CLI 中使用相同的声明来获取匹配的签名。
I'd like to call a method being compiled with /clr:oldsyntax
(Managed Extensions for C++ syntax) from c++ code being compiled with /clr
(C++/CLI). However, I'm having trouble forward declaring the method in C++/CLI such that it matches up to the "Managed Extensions for C++" signature.
The declaration in the version using "Managed Extensions for C++" looks like:
void MangToUnMangDateTime(System::DateTime & managedDT, tm& unmangDT);
Note: The first parameter (managedDT) is the parameter of interest for this question. This results in the following msil for the method (found using ildasm.exe):
.method assembly static void MangToUnMangDateTime(valuetype [mscorlib]System.DateTime& modopt([mscorlib]System.Runtime.CompilerServices.IsImplicitlyDereferenced) managedDT,
valuetype tm* modopt([mscorlib]System.Runtime.CompilerServices.IsImplicitlyDereferenced) unmangDT) cil managed
First Attempt:
My first attempt to forward declare this method in C++/CLI looked like:
void MangToUnMangDateTime2(System::DateTime % managedDT, tm& unmangDT);
which resulted in the following msil:
.method assembly static void MangToUnMangDateTime(valuetype [mscorlib]System.DateTime& managedDT,
valuetype tm* modopt([mscorlib]System.Runtime.CompilerServices.IsImplicitlyDereferenced) unmangDT) cil managed
which matches except for the additional modopt MSIL declarator included in the "Managed Extensions for C++" version:
modopt([mscorlib]System.Runtime.CompilerServices.IsImplicitlyDereferenced)
Second Attempt
My second attempt to forward declare this method in C++/CLI looked like:
MangToUnMangDateTime(System::DateTime & managedDT, tm& unmangDT);
As a side note, I was surpised this compiled in C++/CLI since I expected it to want me to use the % syntax on a managed type. This resulted in the following msil:
.method assembly static void MangToUnMangDateTime(valuetype [mscorlib]System.DateTime* modopt([mscorlib]System.Runtime.CompilerServices.IsImplicitlyDereferenced) managedDT,
valuetype tm* modopt([mscorlib]System.Runtime.CompilerServices.IsImplicitlyDereferenced) unmangDT) cil managed
This one matches the modopt MSIL declarator, but is a pointer *
instead of a reference &
.
Question:
So, is there a way for me to forward declare this in C++/CLI to match the signature in the "Managed Extensions for C++" version? Perhaps via an attribute on the parameter?
Constraints: I do not want to modify the "Managed Extensions for C++" version. Clearly, if I modify the "Managed Extensions for C++" version to be passed by value (which it probably should have been in the first place):
void MangToUnMangDateTime(System::DateTime managedDT, tm& unmangDT);
then I can get the signatures to match by using the same declaration in C++/CLI.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我可能完全错了,但我们不应该首先考虑由“C++ 托管扩展”生成的 IL 被破坏了吗?为什么要向引用参数添加
IsImplicitlyDereferenced
属性?从这个角度来看,我想这是一个答案,说明您可能无法使用 C++/CLI 生成完全相同的签名(但这实际上是一件好事),并且您的第一次尝试确实是正确的方法去。
I may be completely wrong, but shouldn't we consider the IL produced by "Managed Extensions for C++" broken in the first place ? Why would you add an
IsImplicitlyDereferenced
attribute to a reference parameter ?From this point of view, I guess it's an answer to state that you probably won't be able to produce the exact same signature with C++/CLI (but that's actually a good thing), and that your first attempt was indeed the correct way to go.
您可能想要使用 ^ (
System::DateTime^
) - 这在 C++/CLI 中声明托管引用。我对 /oldsyntax 一无所知,但它需要引用 CLR 类型,所以我认为这是等效的。You probably want to use ^ (
System::DateTime^
)- this declares a managed reference in C++/CLI. I don't know anything about /oldsyntax, but it takes a reference to a CLR type, so I'm thinking that this is the equivalent.