本机C++程序在使用 C++/CLI 和 C# 互操作 DLL 启动时崩溃



我需要将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。

感谢每一位提供帮助的人。

最新更新