C++&WPF混合编程

实现方法

本文采用C++ clr作为桥梁,将C++的对象与C#对象可以一一对应,并可以在C#中方便的使用。所以需要在解决方案中再额外添加一个C++ clr的项目。

以下是整个代码结构

Managed引用Native项目,而C#则是很方便的引用Manager。

Native项目 

该项目创建两个类,Machine与MachineStatus。其中Machine中有一个属性是MachineStatus的一个实例。而MachineStatus中又含有两个属性。我们就通过简单的类来了解如何将C++的对象传递给C#的。以下是两个对象的头文件。当然定义了NATIVE_API,用于导出这两个类。

#ifdef NATIVE_EXPORTS
#define NATIVE_API __declspec(dllexport)
#else
#define NATIVE_API __declspec(dllimport)
#endif
#include "MachineStatus.h"
#include <iostream>
namespace native
{
	class NATIVE_API CMachine
	{
	private:
		CMachineStatus m_MachineStatus;
	public:
		std::string Message;
		CMachine(void);
		~CMachine();
		CMachineStatus& GetStatus();
		void SetStatus(CMachineStatus& value);
		void Increase();
		void Run();
		void Pause();
		void Stop();
	};
}

 

#ifdef NATIVE_EXPORTS
#define NATIVE_API __declspec(dllexport)
#else
#define NATIVE_API __declspec(dllimport)
#endif
namespace native
{
	class NATIVE_API CMachineStatus
	{
	private:
		long iWorkStatus = 0;
		long iBondNumber = 0;
	public:
		CMachineStatus();
		~CMachineStatus();
		long GetWorkStatus();
		void SetWorkStatus(long value);
		long GetBondNumber();
		void SetBondNumber(long value);
	};
}

 Managed项目

该项目主要是将C++对象转换成托管类型。首先记得先引用Native项目。然后使用C++ clr的语法对托管对象实例化,主要是取出Native对象的地址,使用其地址创建。

#ifndef _NAME_H
#define _NAME_H
#include "../Native/Machine.h"
#include "MachineStatus.h"
#endif

using namespace System;
using namespace System::Text;
namespace Managed {
	public ref class Machine
	{
	private:
		native::CMachine* m_instance;
	public:
		property String^ Message {String^ get() { return gcnew String(m_instance->Message.c_str()); }};
		property MachineStatus^ Status;
		Machine()
		{
			m_instance = new native::CMachine();
			Status = gcnew MachineStatus(&(m_instance->GetStatus())); 
		}
		~Machine()
		{
			delete m_instance;
		}
		void Run()
		{
			return m_instance->Run();
		}
		void Pause()
		{
			return m_instance->Pause();
		}
		void Stop()
		{
			return m_instance->Stop();
		}
		void Increase()
		{
			return m_instance->Increase();
		}
	};
}
#ifndef _NAME_H
#define _NAME_H
#include "../Native/MachineStatus.h"
#endif

namespace Managed
{
	public ref class MachineStatus
	{
	private:
		native::CMachineStatus* native_Instance;
	public:
		MachineStatus()
		{
			native_Instance = new native::CMachineStatus();
		}
		MachineStatus(native::CMachineStatus* status)
		{
			native_Instance = status;
		}
		~MachineStatus()
		{
			delete(native_Instance);
		}
		property int WorkStatus
		{
		public:
			int get()
			{
				return native_Instance->GetWorkStatus();
			}
			void set(int value)
			{
				native_Instance->SetWorkStatus(value);
			}
		}
		property int BondNumber
		{
		public:
			int get()
			{
				return native_Instance->GetBondNumber();
			}
			void set(int value)
			{
				native_Instance->SetBondNumber(value);
			}
		}
	};
}

WpfApp项目

当托管对象创建后,C#便可以很轻松的使用。所以我创建了一个绑定示例看能不能正常工作

<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp"
        mc:Ignorable="d"
        Title="MainWindow"
        Height="450"
        Width="800"
        FontFamily="Consolas"
        DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}">
    <StackPanel>
        <Button Content="生产加1"
                Click="BtnAdd_Click" />
        <Button Content="启动"
                Click="BtnStart_Click" />
        <Button Content="暂停"
                Click="BtnPause_Click" />
        <Button Content="停止"
                Click="BtnStop_Click" />
        <StackPanel Orientation="Horizontal"
                    Margin="30,20,0,0">
            <TextBlock Text="机器状态" />
            <TextBlock Margin="10,0,50,0"
                       Name="_txbMachineStatus"
                       Text="{Binding Machine.Status.WorkStatus}" />
            <TextBlock Text="生产数" />
            <TextBlock Margin="10,0,50,0"
                       Name="_txbNumber"
                       Text="{Binding Machine.Status.BondNumber}" />
            <TextBlock Text="信息" />
            <TextBlock Margin="10,0,0,0"
                       Text="{Binding Machine.Message}" />
        </StackPanel>
    </StackPanel>
</Window>
using System.Windows;
using System.ComponentModel;
using Managed;
using System;

namespace WpfApp
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public Machine Machine { get; set; } = new Machine();
        public MainWindow()
        {         
            InitializeComponent();
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void BtnStart_Click(object sender, RoutedEventArgs e)
        {
            Machine.Run();
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Machine)));
        }

        private void BtnPause_Click(object sender, RoutedEventArgs e)
        {
            Machine.Pause();
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Machine)));
        }

        private void BtnStop_Click(object sender, RoutedEventArgs e)
        {
            Machine.Stop();
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Machine)));
        }

        private void BtnAdd_Click(object sender, RoutedEventArgs e)
        {
            Machine.Increase();
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Machine)));
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值