在软件开发的历程中,经常会遇到需要与旧代码集成的情况。这些旧代码可能是十年前的FoxPro 2.6,或者其他任何不再流行的编程语言编写的。在这些环境中,从头开始可能并不总是可行的,因此集成新技术往往成为必要。这不仅可以节省开发时间,提供更健壮的解决方案,提高效率和速度,甚至在需要修改特定应用程序时,还能保持理智。
首先,需要为任务开发一个.NET库。有多种方式可以暴露.NET解决方案,但最简单的可能是通过类库来实现,这也是本文使用的方法。请记住,需要通过桥接DLL提供对这个库的访问。可能足够幸运,能够通过一个函数调用来暴露那个库(例如 'object.do_this')。然而,可能需要在调用应用程序和库之间保留状态,使用句柄、参数传递等。
对于那些不熟悉托管和非托管类型转换的人来说,可能需要增加努力来最小化将被桥接DLL调用的函数的参数数量。最小化参数数量通常可以节省很多麻烦。从非托管类型到托管类型,然后再返回(如果参数被返回)的参数转换可能是整个过程中最耗时的部分。可能正在使用char *、CStrings、数组等,它们各自都有其复杂性。然而,一旦做了几次,它就不再是一个问题。
桥接DLL只是一个托管C++ DLL,其中导出带有熟悉的dllexport属性的函数。从这个DLL,将访问.NET库。一旦包含了.NET DLL,并可选地导入了命名空间,.NET库中的设施就可以使用了。可能只需要一个导出的函数来提供对库的访问,或者可能需要几个。可能想要保持桥接DLL尽可能简单,只是一个桥接。然而,可能想要在桥接中提供特定于调用应用程序和库之间交互的设施。这可能为那些尝试实现隔离和数据隐藏技术的人提供一个更优雅的解决方案。
调用应用程序只需要能够加载DLL并调用导出的函数。源代码中给出的示例是一个简单的非托管C++控制台应用程序。它调用了几个桥接函数,并将输出打印到控制台窗口。
其余的细节留给源代码,可以在上面下载。这个过程相对简单,所以包含的源代码应该提供了足够的细节来开始。在调试过程中协调三个项目可能会很棘手,所以它们都被包含在一个单一的解决方案中,有一个共同的输出目录(/common)在解决方案的根目录。桥接DLL和控制台(调用)应用程序构建调试输出到共同目录。然而,vb.NET库构建不会这样做,所以需要将那个构建复制到共同目录。解决方案中的所有路径都是相对的,但如果遇到任何问题,特别是与DLL未加载相关的问题,请确保检查这些路径。
以下是一个简单的代码示例,展示了如何创建一个.NET类库,并通过C++桥接DLL暴露给旧代码。
// .NET类库示例
using System;
namespace MyDotNetLibrary
{
public class MyClass
{
public string MyMethod(string input)
{
return "Hello, " + input;
}
}
}
// C++桥接DLL示例
#include "stdafx.h"
#include
#include
#using "MyDotNetLibrary.dll" as_friend
using namespace System;
using namespace MyDotNetLibrary;
extern "C" __declspec(dllexport) char* MyMethodWrapper(char* input)
{
MyClass myClass;
std::string result = myClass.MyMethod(std::string(input).c_str());
return _strdup(result.c_str());
}