连接 C/C++与.NET

发布于 2024-10-11 18:19:04 字数 720 浏览 5 评论 0原文

我正在考虑在 C++/CLI 中移植应用程序 C/C++。

我主要想利用反射、XML 序列化以及 Microsoft 提供的 .NET 框架中的所有功能(甚至可能是单声道)的潜力。

该项目并未大量使用STL,并且应用程序对象大多是静态分配的。很多代码是用C编写的,还有一些是用C++实现的。

问题在于代码非常非常“长”:这是转换现有代码以使其正常运行所需的时间的问题。

我尝试创建一个用 /clr 中的标志编译的 C++ 项目,毕竟还不错。你可以保留现有的C++代码,但同时使用“托管”类,甚至能够从C++类方法访问“托管”对象。

我发现的缺陷很少,但让我对这种“迁移”感到困惑......

为了利用反射的数据序列化,我所有的数据结构都应该被管理。非托管类不能声明由托管类类型定义的字段。要解决此问题,如果将类转换为由垃圾收集器管理,则声明该类型成员的每个类也将受到管理。

引入托管班可能会遇到哪些困难?

好吧,我在考虑:

  • 字符串管理(我讨厌每次需要时调用 AllocaHGlobal 将 System.String 转换为 char* (例如,作为函数参数) )
  • 数组管理(将经典数组转换为 cli::array)
  • (已经提到)混合托管和非托管类
  • 异常处理
  • 崩溃(核心)转储创建如何受到影响
  • ...任何其他我还没有想到的...

I'm considering porting an application C / C + + in C + + / CLI.

Mainly I would like to exploit the potential of reflection, XML serialization and in general all the features in. NET framework offered by Microsoft (maybe even in mono).

The project in question does not use the STL heavily, and application objects are mostly allocated statically. A lot of code is written in C, another was implemented in C + +.

The problem is that the code is very, very, very "long": this is a problem for the time required for the conversion of the existing code so that it runs properly.

I tried to create a C + + project compiled with flag in / clr, was not so bad after all. you can keep your existing code C + +, but in the meantime use the classes "managed", is even able to access "managed" objects from C + + class methods.

The flaws that I found very few, but make me puzzled about this "migration" ...

To take advantage of the data serialization using reflection, all my data structures should be managed. An unmanaged class can not declare fields as defined by a type of managed class. To resolve this problem if a class is converted so that it is managed by the garbage collector, every class that declares a member of that type to be managed as well.

What difficulties may be encountered during the introduction of managed classes?

Well, I'm thinking about:

  • String management (I hate to call AllocaHGlobal to convert System.String to char* each time I need it (for example, as function parameter)
  • Array management (conversion of classical arrays to cli::array)
  • (already mentioned) mixing managed and unmanaged classes
  • exception handling
  • crash (core) dump creation how is affected
  • ...any other that I haven't thought yet...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

寻找我们的幸福 2024-10-18 18:19:04

非托管类可以拥有托管成员。诀窍是使用 gcroot 模板。看这里

http ://weblogs.asp.net/kennykerr/archive/2005/07/12/Mishing-Native-and-Managed-Types-in-C_2B002B00_.aspx

了解更多信息。

编辑:作为对您其他一些问题的回应:当您有一个工作的 C++ 代码库太大时,您必须期待来自生产的更改请求,同时您正在处理 C++/CLI 端口,恕我直言,这是最好的方法是为了避免拥有相同代码库的两个副本。相反,尝试使用#ifdef、宏、生成器等使相同的代码可以用 C++ 和 C++/CLI 进行编译。我知道这是可能的,因为这正是我们不久前所做的移植约 120.000 行代码的程序。

对于字符串转换,我们使用以下代码:(

typedef System::String^ SysString;

inline SysString Std2Sys(const std::string &s)
{
    return gcnew System::String(s.c_str());
}

inline std::string Sys2Std(SysString ss) {
    using namespace System::Runtime::InteropServices;
    const char* chars = 
      (const char*)(Marshal::StringToHGlobalAnsi(ss)).ToPointer();
    std::string s = chars;
    Marshal::FreeHGlobal(System::IntPtr((void*)chars));
    return s;
}

在我们的情况下,性能从来不是问题,在您的情况下可能有所不同,但如果没有任何需要,请不要尝试优化任何内容)。

Unmanaged classes can have managed members. The trick is to use the gcroot template. Look here

http://weblogs.asp.net/kennykerr/archive/2005/07/12/Mixing-Native-and-Managed-Types-in-C_2B002B00_.aspx

to learn more about it.

EDIT: as a response to some of your other questions: when you have a working C++ code base which is so big that you have to expect change requests from production while in parallel you are working on the C++/CLI port, IMHO the best approach is to avoid having two copies of the same code base. Instead, try to make the same code compilable both with C++ and C++/CLI, using #ifdef's, macros, generators etc. I know that's possible since this is exact what we did some time ago when porting a program of ~120.000 lines of code.

For string conversion, we were using this code:

typedef System::String^ SysString;

inline SysString Std2Sys(const std::string &s)
{
    return gcnew System::String(s.c_str());
}

inline std::string Sys2Std(SysString ss) {
    using namespace System::Runtime::InteropServices;
    const char* chars = 
      (const char*)(Marshal::StringToHGlobalAnsi(ss)).ToPointer();
    std::string s = chars;
    Marshal::FreeHGlobal(System::IntPtr((void*)chars));
    return s;
}

(performance was never an issue with that in our case, might be different in yours, but don't try to optimize anything if there is not any need to).

猫弦 2024-10-18 18:19:04

Doc Brown 关于 gcroot 提出了很好的观点。相反,托管类可以具有指向本机“子对象”的指针。

通常需要在 auto_ptrshared_ptr 上创建互操作变体,以便编译器生成所有样板文件以在父对象消亡时丢弃子对象,即使是托管和非托管的混合也是如此。

如果字符串转换让您抓狂,您可能需要查看 C++/CLI 中包含的 marshall_as 模板。

Doc Brown makes a good point about gcroot. And conversely, managed classes can have pointers to native "subobjects".

It's generally desirable to create interop variants on auto_ptr or shared_ptr so the compiler generates all the boilerplate to discard subobjects when the parent object dies, even with a mix of managed and unmanaged.

If string conversion is driving you nuts, you might want to look at the marshall_as template included with C++/CLI.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文