C#与非托管C ++的互操作性的持续传奇 [英] A continued saga of C# interoprability with unmanaged C++

查看:135
本文介绍了C#与非托管C ++的互操作性的持续传奇的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

经过一天将我的头撞到墙上的字面意思和隐喻,我请求帮助:



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

为了简单起见,我将附上一些基本的测试代码。



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



tester.h

  #pragma once 
externCclass __declspec(dllexport)NativeTester
{
public:
void NativeTest
};

tester.cpp

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

Interop Project有以下文件:



InteropLib.h

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



最后,WPF项目有一个窗口反映Interop项目:



MainWindow.xaml.cs

  
使用System.Windows;
使用InteropLib;
命名空间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文件。



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



p>

解决方案

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

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

类EXPORTED NativeTester {
//等。
};在你的测试项目中,使用C / C ++,预处理器,预处理器定义,并添加BUILDING_DLL。 p>

接下来的事情是确保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了。


After a day of banging my head against the wall both literally and metaphorically, I plead for help:

I have an unmanaged C++ project, which is compiled as a DLL. Let's call it CPP Project. It currently works in an unmanaged environment. In addition, I have created a WPF project, that shall be called WPF Project. This project is a simple and currently almost empty project. It contains a single window and I want it to use code from Project 1. For that, I have created a CLR C++ project, which shall be called Interop Project and is also compiled as a DLL.

For simplicity I will attach some basic testing code I have boiled down to the basics.

CPP Project has the following two testing files:

tester.h

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

tester.cpp

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

Interop Project has the following file:

InteropLib.h

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

Lastly, WPF Project has a single window refrencing Interop Project:

MainWindow.xaml.cs

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

And the XAML itself has an empty window (default created).

Once I am trying to run the WPF project, I get the following error:

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()

Interestingly enough, if I do not export the class from CPP Project, I do not get this error. Say, if i change tester.h to:

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

However, in this case I cannot use my more complex classes. If I move my implementation to a cpp file like before, I get unresolved linkage errors due to my not exporting my code. The C++ code I want to actually use is large and has many classes and is object oriented, so I can't just move all my implementation to the h files.

Please help me understand this horrific error I've been trying resolve without success.

Thanks.

解决方案

This went wrong right from the start, your tester.h file is not correct. The class should only have the __declspec(dllexport) attribute when you are building the tester project. Any other project that uses the DLL must see the class with the __declspec(dllimport) attribute. Start fixing this by using a macro in tester.h:

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

class EXPORTED NativeTester {
    // etc..
};

And in your tester project, use C/C++, Preprocessor, Preprocessor Definitions and add BUILDING_DLL.

Next thing is to make sure that the DLL is being stored in the right directory. Which is what the exception is complaining about, it can't find the DLL. The build directory for C++ projects is Debug but for WPF projects it is bin\Debug. Fix that by changing the General + Output Directory setting, make it $(SolutionDir)$bin\(ConfigurationName).

Build the C++ project and verify that you can find the DLL back in the Solution's bin\Debug directory. And check that you also have the .lib file, you'll need that when you build the C++/CLI project. As an extra verification step, run Dumpbin.exe /exports foo.dll from the Visual Studio Command Prompt and check that you indeed see the class getting exported.

The C++/CLI project next, you need to change the Output Directory setting the same way. Add the .lib file to the linker's Additional Dependencies properties. You'll get the kind of linker errors you were talking about if you skip that step. Build it and verify that you get the DLL in the correct bin\Debug directory again.

Repeat these changes for the Release configuration.

Set the project dependencies, the WPF project depends on the C++/CLI project. The C++/CLI project depends on the C++ project. This ensures the projects are getting built in the right order.

You should now have a good shot at using these DLLs in your WPF project.

这篇关于C#与非托管C ++的互操作性的持续传奇的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆