65.9K
CodeProject 正在变化。 阅读更多。
Home

在托管代码和非托管代码之间移动数据 – 使用 C++ 和 IJW 的替代方法

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.75/5 (5投票s)

2009年4月15日

CPOL

3分钟阅读

viewsIcon

44728

在托管代码和非托管代码之间移动数据 – 使用 C++ 和 IJW 的替代方法

引言

现在,在 Microsoft 环境中编写新软件时,自然的选择是 C#。 由于各种原因,项目的某些部分可能需要用其他语言编写(现有包、第三方、性能等)。 在这篇短文中,我将提出一个我认为很好的、易于管理的托管代码和非托管代码互操作的替代方案。

.NET 环境

微软嫉妒 Java,并创建了自己的虚拟机 CLR。 C# 代码的编译生成适用于此虚拟机的机器代码。 微软更进一步,其他语言(如 C++)的代码也被编译成相同的机器语言。 因此,可以从 C# 中的 DLL 或可执行文件调用 C++ 中的 DLL,反之亦然。 每个团队使用其首选编程语言,并且所有内容都适合在链接中。

托管代码 vs. 非托管代码

在 .NET 环境中运行的代码称为托管代码。 像过去一样运行的代码称为非托管代码。“管理”带来了很多优势,例如“垃圾回收”,即回收已分配但永远不会再次使用的内存。 “管理”的缺点是性能较低,以及难以与非托管代码中的现有库进行交互。

IJW

微软提供了一个友好的解决方案,据我所知,该解决方案仅适用于 C++。 该解决方案可以从托管代码调用非托管代码,反之亦然,它“即时工作!”唯一的限制是,在非托管代码中不会使用“托管”数据类型。 因此,可以传递基本数据类型,例如 intdouble 以及定义为“非托管”的数据类型。 为了使用该功能,我们将创建一个新的 DLL 或可执行文件,作为 CLR (托管) 的 C++ 项目,然后我们将用以下代码包围非托管代码:

#pragma unmanaged

#pragma managed

用例示例和代码片段

在一个项目中,我在 C# 中定义了一些类,并创建了一个 DLL 来保存这些类。 这些类旨在表示实时程序的配置。 我们决定实时循环和逻辑将用非托管 C++ 代码编写。 我创建了另一个用 C++ 编写并使用 CLR 的 DLL。 这样,用 C++ 编写的 DLL 可以引用用 C# 编写的 DLL,并使用表示配置的类。 包装所有内容的程序本身是用 C# 编写的。 因此,该程序熟悉 C# DLL 中的类。 它将它们传递给 C++ DLL,后者也熟悉这些类。 仍然存在一个问题。 为了调用非托管代码,我们需要将“托管”数据类型转换为“非托管”数据类型。 这里涉及的工作要么是微不足道的,要么是西西弗斯式的,但它绝对是不用动脑筋的。 还有另一种替代方法,即在非托管代码和托管代码中使用非托管数据类型。 我建议显式转换更方便、更易于理解,并且在托管代码和非托管代码之间的边界上最后一刻完成。

以下是一个代码片段

*.h 文件 (C++)

public ref class CConfig 
{ 
public: 
    CConfig (int _a, String ^_str, double _d); 
    void doTheStuff (); 
    int m_a; 
    String ^m_str; 
    double m_d; 
};

*.cpp 文件

#include <stdio.h> 
#include <stdlib.h> 
#include <vcclr.h> 
#include <iostream> 
void someMoreInManaged () 
{ 
    Console::WriteLine("C++ Managed – someMoreInManaged"); 
} 

#pragma unmanaged 
void doTheStuff1 (int _a, double _d, const wchar_t* const _str) { 
    std::cout << "C++ unmanaged – doTheStuff1" << std::endl; 
    std::cout << _a << _std::endl; 
    printf_s("%S\n", _str); 
    std::cout << _d << _std::endl; 
    someMoreInManaged(); 
} 

#pragma managed 
CConfig::CConfig 
(int _a, String ^_str, double _d) { 
    m_a = _a; 
    m_str = _str; 
    m_d = _d; 
} 
void CConfig::doTheStuff () { 
    Console::WriteLine("C++ Managed – doTheStuff"); 
    // Pin memory so GC can't move it while 
    // native function is called – MSDN documentation wchar_t <-> String 
    pin_ptr<const wchar_t> wch = PtrToStringChars(m_str); 
    doTheStuff1 (m_a,m_d,wch); 
}

历史

  • 2009 年 4 月 15 日:初始发布
© . All rights reserved.