C++/CLI 包装引用 Native C++ 简单测试

发布时间 2023-12-07 13:34:47作者: double64

托管C++

这个项目名:CppCLI

Animals.h

#pragma once
using namespace System;

namespace Zoological
{
    public ref class Animals
    {
    public:
        int GetLegs();
        void SetLegs(int legs);
        String^ GetName();
        void SetName(String^ name);
    private:
        int m_Legs;
        String^ m_Name;
    };
}

Animals.cpp

#include "pch.h"
#include "Animals.h"
namespace Zoological
{
    int Animals::GetLegs()
    {
        return m_Legs;
    }

    void Animals::SetLegs(int legs)
    {
        m_Legs = legs;
    }

    String^ Animals::GetName()
    {
        return m_Name;
    }

    void Animals::SetName(String^ name)
    {
        m_Name = name;
    }
}

主函数:

#include "pch.h"
#include "Animals.h"

using namespace System;

int main(array<System::String ^> ^args)
{
    using namespace Zoological;    // 命名空间
    Animals^ animal = gcnew Animals();

    animal->SetLegs(4);
    animal->SetName("小狗");
    
    Console::WriteLine("{0}有 {1} 条腿", animal->GetName(), animal->GetLegs());
    return 0;
}

输出:

小狗有 4 条腿



C# 直接调用

将上面的托管 C++ 生成 Dll, 新建一个 C# 程序, 引用 dll 可以直接调用:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Zoological;  // 引用命名空间

namespace ConsoleApp19_CSCPPCLI
{
    class Program
    {
        static void Main(string[] args)
        {
            Animals animals = new Animals();
            animals.SetName("小狗");
            animals.SetLegs(4);
            Console.WriteLine($"{animals.GetName()}有 {animals.GetLegs()} 条腿。");
            Console.ReadKey();
        }
    }
}

输出:

小狗有 4 条腿。




C++/CLI 托管 C++ 包装 Native C++

Native C++

新增 NativeCpp 项目:

Animals.h

#pragma once

#include <string>
#define DllExport   __declspec(dllexport)

namespace ZoologicalNative
{
    class DllExport Animals
    {
    public:
        int GetLegs();
        void SetLegs(int legs);
        std::string GetName();
        void SetName(std::string name);
    private:
        int m_Legs;
        std::string m_Name;
    };
}

Animals.cpp

#include "Animals.h"

namespace ZoologicalNative
{
    int Animals::GetLegs()
    {
        return m_Legs;
    }

    void Animals::SetLegs(int legs)
    {
        m_Legs = legs;
    }

    std::string Animals::GetName()
    {
        return m_Name;
    }

    void Animals::SetName(std::string name)
    {
        m_Name = name;
    }
}

托管 C++/CLI 中包装

这个项目名:CppCLI

Animals.h

#pragma once
#include "../NativeCpp/Animals.h"
using namespace System;

namespace Zoological
{
    public ref class Animals
    {
    public:
        Animals();
        ~Animals();
        int GetLegs();
        void SetLegs(int legs);
        String^ GetName();
        void SetName(String^ name);
    private:
        ZoologicalNative::Animals* m_pImpl;
    };
}

Animals.cpp

#include "pch.h"
#include "Animals.h"
#include <string>
//#include <msclr\marshal.h>
//#include "msclr/marshal_windows.h"
//#include "msclr/marshal_cppstd.h"
//#include "msclr/marshal_atl.h"

#pragma comment(lib, "../Debug/NativeCpp.lib")

namespace Zoological
{
    Animals::Animals()
    {
        m_pImpl = new  ZoologicalNative::Animals();
    }

    Animals::~Animals()
    {
        delete m_pImpl;
    }

    int Animals::GetLegs()
    {
        return  m_pImpl->GetLegs();
    }

    void Animals::SetLegs(int legs)
    {
        m_pImpl->SetLegs(legs);
    }

    String^ Animals::GetName()
    {
        //return msclr::interop::marshal_as<String^>(m_Animals->GetName());  // 这个不行 指针不允许指向 ref class

        std::string name = m_pImpl->GetName();
        const char* c_name = name.c_str();
        String^ cli_name = gcnew String(c_name);

        return cli_name;
    }

    void Animals::SetName(String^ name)
    {
        // 这个不行 指针不允许指向 ref class
        /*  std::string name_std = msclr::interop::marshal_as<std::string>(name);
          m_Animals->SetName(name_std);*/

        using namespace System::Runtime::InteropServices;
        char* c_name = (char*)(void*)Marshal::StringToHGlobalAnsi(name);
        std::string s_name = std::string(c_name);
        m_pImpl->SetName(s_name);
    }
}

主函数:

#include "pch.h"
#include "Animals.h"

using namespace System;

int main(array<System::String ^> ^args)
{
    using namespace Zoological;
    Animals^ animal = gcnew Animals();

    animal->SetLegs(4);
    animal->SetName("哮天犬");
    
    Console::WriteLine("{0} 有 {1} 条腿", animal->GetName(), animal->GetLegs());
    return 0;
}

输出:

哮天犬 有 4 条腿

托管 C++ 导出 DLL 给到 C# 调用

这个引用好CppCLI.dll,直接调用没什么特别的。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Zoological;

namespace ConsoleApp19_CSCPPCLI
{
    class Program
    {
        static void Main(string[] args)
        {
            Animals animals = new Animals();
            animals.SetName("牛魔王");
            animals.SetLegs(4);
            Console.WriteLine($"{animals.GetName()}有 {animals.GetLegs()} 条腿。");
            Console.ReadKey();
        }
    }
}

输出:

牛魔王有 4 条腿。

▲ C# 项目引用