我需要将C#WPF UserControls包装在C++/CLI包装中,以便在本机C++程序中使用。本机程序大量使用MFC,并在VS2010中编译。我已经在一个单独的解决方案中正确地生成了C++/CLI.lib和.dll文件,并从MFC应用程序链接到它们,该应用程序成功地编译和链接,像往常一样生成了可执行文件。然而,当我启动MFC应用程序时,在它进入main()之前,我就收到了一个访问冲突错误0xc0000005。当我注释掉包装器代码时,程序会正常启动。
为了尝试隔离这个问题,我尝试创建一个完全独立的本机C++项目,其唯一目的是用伪数据调用包装类。这个项目到达main(),但当我调用包装类的构造函数时抛出异常(0xe043352)。
我已经尝试过寻找任何可能的解决方案,但最符合我的情况的是检查函数签名,以确保我传递了正确数量的参数(我是)。我还从独立项目中查找了0xe043352异常,它似乎是一个通用的.NET异常。
我也看到了这个问题的张贴,但希望解决方案会比这更简单。我一直在按照这个博客上的说明创建包装器类。
除了MFC应用程序代码之外,我包含了所有代码,因为它甚至没有加载到main()。我希望如果我能在全新的项目中解决这个问题,MFC应用程序就会启动。
C#WPF:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace ManagedWPFLink
{
public struct TestResultData
{
public string inspectionType;
public string testResult;
public string measuredValue;
public string passCondition;
public string comments;
}
/// <summary>
/// Interaction logic for TestResultsDialog.xaml
/// </summary>
public partial class TestResultsDialog : UserControl
{
private Window window;
public TestResultsDialog()
{
InitializeComponent();
DataGridTextColumn col1 = new DataGridTextColumn();
DataGridTextColumn col2 = new DataGridTextColumn();
DataGridTextColumn col3 = new DataGridTextColumn();
DataGridTextColumn col4 = new DataGridTextColumn();
DataGridTextColumn col5 = new DataGridTextColumn();
this.testResultsGrid.Columns.Add(col1);
this.testResultsGrid.Columns.Add(col2);
this.testResultsGrid.Columns.Add(col3);
this.testResultsGrid.Columns.Add(col4);
this.testResultsGrid.Columns.Add(col5);
col1.Binding = new Binding("inspectionType");
col2.Binding = new Binding("testResult");
col3.Binding = new Binding("measuredValue");
col4.Binding = new Binding("passCondition");
col5.Binding = new Binding("comments");
col1.Header = "Inspection Type";
col2.Header = "Test Result";
col3.Header = "Measured Value";
col4.Header = "Pass Condition";
col5.Header = "Comments";
this.window = new Window
{
Title = "Inspection Results",
Content = this,
SizeToContent = SizeToContent.WidthAndHeight,
ResizeMode = ResizeMode.NoResize
};
}
public void addRow(string inspectionType, string testResult, string measuredValue, string passCondition, string comments)
{
TestResultData data = new TestResultData();
data.inspectionType = inspectionType;
data.testResult = testResult;
data.measuredValue = measuredValue;
data.passCondition = passCondition;
data.comments = comments;
this.testResultsGrid.Items.Add(data);
}
public void deleteAllRows()
{
this.testResultsGrid.Items.Clear();
}
public void showDialog()
{
this.window.ShowDialog();
}
}
}
C
<UserControl x:Class="ManagedWPFLink.TestResultsDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="400" d:DesignWidth="600">
<Grid>
<DataGrid AutoGenerateColumns="True" Height="376" HorizontalAlignment="Left" Margin="12,12,0,0" Name="testResultsGrid" VerticalAlignment="Top" Width="576" ItemsSource="{Binding}" MinColumnWidth="40">
</DataGrid>
</Grid>
</UserControl>
C++/CLI头:
// ManagedWPFLink.h
#pragma once
namespace WPFLink
{
class WPFPrivate;
class __declspec(dllexport) WPFWrapper
{
private:
WPFPrivate *internalWrapper;
public:
WPFWrapper();
~WPFWrapper();
void addItems(const char **data);
void deleteAllRows();
void showDialog();
};
}
C++/CLI来源:
// This is the main DLL file.
#include "stdafx.h"
#using <WindowsBase.dll>
#using <PresentationCore.dll>
#using <PresentationFramework.dll>
#using "ManagedWPFLink.dll"
#include "WPFLink.h"
using namespace System::Runtime::InteropServices;
namespace WPFLink
{
public class WPFPrivate
{
public:
msclr::auto_gcroot<System::String^> inspectionType;
msclr::auto_gcroot<System::String^> testResult;
msclr::auto_gcroot<System::String^> measuredValue;
msclr::auto_gcroot<System::String^> passCondition;
msclr::auto_gcroot<System::String^> comments;
msclr::auto_gcroot<ManagedWPFLink::TestResultsDialog^> testResultDialog;
public:
WPFPrivate()
{
}
~WPFPrivate()
{
delete testResultDialog;
}
};
WPFWrapper::WPFWrapper()
{
this->internalWrapper = new WPFLink::WPFPrivate();
}
WPFWrapper::~WPFWrapper()
{
delete this->internalWrapper;
}
void WPFWrapper::addItems(const char **data)
{
this->internalWrapper->inspectionType = gcnew System::String(data[0]);
this->internalWrapper->testResult = gcnew System::String(data[1]);
this->internalWrapper->measuredValue = gcnew System::String(data[2]);
this->internalWrapper->passCondition = gcnew System::String(data[3]);
this->internalWrapper->comments = gcnew System::String(data[4]);
this->internalWrapper->testResultDialog->addRow(this->internalWrapper->inspectionType, this->internalWrapper->testResult,
this->internalWrapper->measuredValue, this->internalWrapper->passCondition, this->internalWrapper->comments);
}
void WPFWrapper::deleteAllRows()
{
this->internalWrapper->testResultDialog->deleteAllRows();
}
void WPFWrapper::showDialog()
{
this->internalWrapper->testResultDialog->showDialog();
}
}
原生C++代码:
#include "..WPFLinkWPFLink.h"
int main()
{
WPFLink::WPFWrapper wrapper; // Generates 0xe0434352 error
return 0;
}
经过多次头发拉扯,我在这里使用了本文中的方法:http://www.codeguru.com/cpp/cpp/cpp_managed/nfc/article.php/c14589/Hosting-WPF-Content-in-an-MFC-Application.htm
我使用相关的代码生成了HWND,该程序与我自己的原生C++代码完美地结合在一起。然而,在我们的主要MFC应用程序启动时,我仍然遇到访问冲突,我根本没有设法缩小访问范围。我所掌握的唯一信息是,如果我试图链接到我的DLL,程序就会崩溃。我将不得不放弃这种链接到stub.lib文件并加载必要DLL的方法,而是重做接口,只使用extern"C"函数,并在我的DLL上手动调用LoadLibrary。
感谢每一位提供帮助的人。