本机C ++程序在启动时崩溃,使用C ++ / CLI& C#interop DLL

时间:2015-11-10 00:36:02

标签: c# c++ .net wpf c++-cli

我遇到需要在C ++ / CLI包装器中包装C#WPF UserControl以在本机C ++程序中使用的情况。本机程序大量使用MFC,并在VS2010中编译。我已经在单独的解决方案中正确生成了C ++ / CLI .lib和.dll文件,并从MFC应用程序链接到它们,MFC应用程序成功编译和链接,像往常一样生成可执行文件。但是,当我去启动MFC应用程序时,我甚至在访问main()之前得到访问冲突错误0xc0000005。当我注释掉包装代码时,程序会正常启动。

为了尝试隔离问题,我尝试创建一个完全独立的本机C ++项目,其唯一目的是使用虚拟数据调用包装类。这个项目到达main()但是当我调用包装类的构造函数时抛出异常(0xe0434352)。

我已经尝试过搜索任何可能的解决方案,但是与我的情况最匹配的解决方案是检查函数签名以确保我传递正确数量的参数(我是)。我还从独立项目中查找了0xe0434352异常,它似乎是一个通用的.NET异常。

我也看到this问题,但希望解决方案比这更简单。我一直在关注this博客上的说明来创建包装类。

我包含了MFC应用程序代码以外的所有代码,因为它甚至没有加载到main()。我希望如果我能够在全新项目中解决问题,MFC应用程序将启动。

C#WPF:

import pandas 
import numpy
import matplotlib.pyplot as plt
import seaborn

data = pandas.read_csv('fy15crime.csv', low_memory = False)
seaborn.countplot(x="primary_type", data=data)
plt.xlabel('crime')
plt.ylabel('amount')

seaborn.plt.show()

C#XAML:

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 ++ / CLI标题:

<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 ++代码:

// 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();
    }
}

1 个答案:

答案 0 :(得分: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,程序崩溃。我将不得不放弃这种链接到存根.lib文件并加载必要的DLL的方法,而是重做接口只使用 extern“C”函数并在我的DLL上手动调用LoadLibrary。

感谢所有试图提供帮助的人。