2012-09-20 89 views
4

C#interoprability的传奇逐字地和比喻敲我的头靠在墙上的一天后,我恳求帮助:持续与非托管C++

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

为了简单起见,我将附上一些基本的测试代码,我将其归结为基础知识。

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

tester.h

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

tester.cpp

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

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

InteropLib.h

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

最后,WPF项目有一个窗口refrencing互操作计划:

MainWindow.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: 'The invocation of the constructor on type 'AppGUI.MainWindow' that matches the specified binding constraints threw an exception.' Line number '3' and line position '9'. ---> System.IO.FileNotFoundException: Could not load file or assembly 'InteropLib.dll' or one of its dependencies. The specified module could not be found.
at AppGUI.MainWindow..ctor()

有趣的是,如果我不从CPP项目导出类,我没有得到这个错误。再说了,如果我改变tester.h到:

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

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

请帮我理解这个可怕的错误,我一直在努力解决没有成功。

谢谢。

+1

专注于_native_ C++部分,您可以使用您的DLL从本机代码?我怀疑'__declspec(dllexport)'导出的方式......更常用的方法是使用基于上下文扩展到'__declspec(dllexport/dllimport)'的预处理器机器和宏。有关详细信息,请参阅[本文](http://www.codeproject.com/Articles/28969/HowTo-Export-C-classes-from-a-DLL)。 –

+0

确保将interop DLL和本机DLL放在应用程序路径中。 VS会复制前者而不是后者。 –

+0

Alexandre C.我在一个目录中拥有所有的DLL和可执行文件。 user1629821,我会检查链接,看看我是否错过了一些东西。 – Gilad

回答

3

从一开始就出错了,您的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。修改通用+输出目录设置,使其成为$(SolutionDir)$bin\(ConfigurationName)

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

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

对版本配置重复这些更改。

设置项目依赖关系,WPF项目依赖于C++/CLI项目。 C++/CLI项目依赖于C++项目。这确保项目按照正确的顺序建立。

您现在应该在WPF项目中使用这些DLL。

+0

我会尽快尝试。我会更新。谢谢! – Gilad

+0

它的工作!再次谢谢你! – Gilad