5

经过一天的从字面上和比喻上把我的头撞到墙上后,我请求帮助:

我有一个非托管 C++ 项目,它被编译为 DLL。我们称之为CPP 项目。它目前在非托管环境中工作。另外,我创建了一个 WPF 项目,名为WPF Project。这个项目是一个简单且目前几乎是空的项目。它包含一个窗口,我希望它使用项目 1 中的代码。为此,我创建了一个 CLR C++ 项目,该项目应称为Interop Project,也被编译为 DLL。

为简单起见,我将附上一些我已经归结为基础的基本测试代码。

CPP项目有以下两个测试文件:

测试者.h

#pragma once
extern "C" class __declspec(dllexport) NativeTester
{
public:
    void NativeTest();
};

测试器.cpp

#include "tester.h"
    void NativeTester::NativeTest()
    {
        int i = 0;
    }

互操作项目具有以下文件:

互操作库

#pragma once
#include <tester.h>
using namespace System;
namespace InteropLib {
    public ref class InteropProject
    {
    public:
        static void Test()
        {
            NativeTester nativeTester;
            nativeTester.NativeTest();
        }
    };
}

最后,WPF 项目有一个引用互操作项目的单一窗口:

主窗口.xaml.cs

using System;
using System.Windows;
using InteropLib;
namespace AppGUI
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            InteropProject.Test();
        }
    }
}

XAML 本身有一个空窗口(默认创建)。

一旦我尝试运行 WPF 项目,就会收到以下错误:

System.Windows.Markup.XamlParseException:'调用与指定绑定约束匹配的类型'AppGUI.MainWindow'的构造函数引发异常。行号“3”和行位置“9”。---> System.IO.FileNotFoundException:无法加载文件或程序集“InteropLib.dll”或其依赖项之一。指定的模块无法找到。
在 AppGUI.MainWindow..ctor()

有趣的是,如果我不从 CPP 项目中导出类,我不会收到此错误。说,如果我tester.h改为:

#pragma once
class NativeTester
{
public:
    void NativeTest()
    {
        int i = 0;
    }
};

但是,在这种情况下,我不能使用更复杂的类。如果我像以前一样将我的实现移动到一个 cpp 文件,由于我没有导出我的代码,我会得到未解决的链接错误。我想要实际使用的 C++ 代码很大并且有很多类并且是面向对象的,所以我不能将我的所有实现都移到 h 文件中。

请帮助我理解这个可怕的错误,我一直在尝试解决但没有成功。

谢谢。

4

1 回答 1

4

这从一开始就出错了,您的 tester.h 文件不正确。当您构建测试器项目时,该类应该只具有 __declspec(dllexport) 属性。使用 DLL 的任何其他项目都必须看到具有 __declspec(dllimport) 属性的类。通过在 tester.h 中使用宏开始修复此问题:

#undef EXPORTED
#ifdef BUILDING_DLL
#   define EXPORTED __declspec(dllexport)
#else
#   define EXPORTED __declspec(dllimport)
#endif

class EXPORTED NativeTester {
    // etc..
};

在您的测试器项目中,使用 C/C++、预处理器、预处理器定义并添加 BUILDING_DLL。

接下来是确保 DLL 存储在正确的目录中。这就是异常所抱怨的,它找不到 DLL。C++ 项目的构建目录是 Debug,但 WPF 项目的构建目录是 bin\Debug。通过更改 General + Output Directory 设置来解决此问题,使其$(SolutionDir)$bin\(ConfigurationName).

构建 C++ 项目并验证您是否可以在解决方案的 bin\Debug 目录中找到该 DLL。并检查您是否还有 .lib 文件,在构建 C++/CLI 项目时需要它。作为额外的验证步骤,从 Visual Studio 命令提示符运行 Dumpbin.exe /exports foo.dll 并检查您是否确实看到了导出的类。

接下来的 C++/CLI 项目,您需要以相同的方式更改输出目录设置。将 .lib 文件添加到链接器的 Additional Dependencies 属性中。如果您跳过该步骤,您将得到您所说的那种链接器错误。构建它并再次验证您是否在正确的 bin\Debug 目录中获得了 DLL。

对发布配置重复这些更改。

设置项目依赖,WPF项目依赖C++/CLI项目。C++/CLI 项目依赖于 C++ 项目。这可确保项目以正确的顺序构建。

您现在应该可以很好地在 WPF 项目中使用这些 DLL。

于 2012-09-20T13:37:23.257 回答