簡體   English   中英

C# 使用 CLI 包裝器調用非托管 C++

[英]C# calling unmanaged C++ using CLI wrapper

我一直在閱讀這里和其他來源的多個示例,了解如何實現這一點。 最近我關注了這個特定的例子,它與多個其他類似的問題相關聯。

https://dorodnic.com/blog/2014/12/10/calling-cpp-by-example/

但是,即使直接從 github 導入此項目,它仍然會在 C# 項目中出現錯誤,無法引用 C++ CLI 代碼。 “找不到類型或命名空間(您是否缺少 using 指令或程序集引用)”。 這與我自己在遵循其他示例時發現的錯誤相同。 任何人都可以向我解釋為什么會失敗和/或建議修復它的步驟嗎?

編輯:在此處添加代碼以節省時間。

//Logic.h
#pragma once

namespace MeaningOfLife
{
    namespace Cpp
    {
        // This is our native implementation
        // It's marked with __declspec(dllexport) 
        // to be visible from outside the DLL boundaries
        class __declspec(dllexport) Logic
        {
        public:
            int Get() const; // That's where our code goes
        };
    }
}
//Logic.cpp
#include "Logic.h"

int MeaningOfLife::Cpp::Logic::Get() const
{
    return 42; // Really, what else did you expect?
}
//Logic.h CLI
#pragma once

namespace MeaningOfLife
{
    namespace Cpp
    {
        // First a Forward Declaration to Cpp::Logic class:
        class Logic; // This allows us to mention it in this header file
        // without actually including the native version of Logic.h

        namespace CLI
        {
            // Next is the managed wrapper of Logic:
            public ref class Logic
            {
            public:
                // Managed wrappers are generally less concerned 
                // with copy constructors and operators, since .NET will
                // not call them most of the time.
                // The methods that do actually matter are:
                // The constructor, the "destructor" and the finalizer
                Logic();
                ~Logic();
                !Logic();

                int Get();

                void Destroy();

                static void InitializeLibrary(System::String^ path);
            private:
                // Pointer to our implementation
                Cpp::Logic* _impl;
            };
        }
    }   
}
//Logic.cpp CLI
#include "Logic.h"
#include "..\MeaningOfLife.Cpp\Logic.h"
#include <string>
#include <Windows.h>

using namespace std;

MeaningOfLife::Cpp::CLI::Logic::Logic()
    : _impl(new Cpp::Logic()) 
    // Allocate some memory for the native implementation
{
}

int MeaningOfLife::Cpp::CLI::Logic::Get()
{
    return _impl->Get(); // Call native Get
}

void MeaningOfLife::Cpp::CLI::Logic::Destroy()
{
    if (_impl != nullptr)
    {
        delete _impl;
        _impl = nullptr;
    }
}

MeaningOfLife::Cpp::CLI::Logic::~Logic()
{
    // C++ CLI compiler will automaticly make all ref classes implement IDisposable.
    // The default implementation will invoke this method + call GC.SuspendFinalize.
    Destroy(); // Clean-up any native resources 
}

MeaningOfLife::Cpp::CLI::Logic::!Logic()
{
    // This is the finalizer
    // It's essentially a fail-safe, and will get called
    // in case Logic was not used inside a using block.
    Destroy(); // Clean-up any native resources 
}

string ManagedStringToStdString(System::String^ str)
{
    cli::array<unsigned char>^ bytes = System::Text::Encoding::ASCII->GetBytes(str);
    pin_ptr<unsigned char> pinned = &bytes[0];
    std::string nativeString((char*)pinned, bytes->Length);
    return nativeString;
}

void MeaningOfLife::Cpp::CLI::Logic::InitializeLibrary(System::String^ path)
{
    string nativePath = ManagedStringToStdString(path);
    LoadLibrary(nativePath.c_str()); // Actually load the delayed library from specific location
}
//C#
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace MeaningOfLife.WPF
{
    using Cpp.CLI;
    using Microsoft.Win32;

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            var fileOpenDialog = new OpenFileDialog
            {
                CheckFileExists = true,
                Filter = "Native Library|MeaningOfLife.Cpp.dll",
                InitialDirectory = Environment.CurrentDirectory
            };

            var result = fileOpenDialog.ShowDialog(this);
            if (result.HasValue && result.Value)
            {
                Logic.InitializeLibrary(fileOpenDialog.FileName);

                using (var wrapper = new Logic())
                {
                    MessageBox.Show("The answer is " + wrapper.Get());
                }
            }
        }
    }
}

錯誤發生在 using Cpp.CLI 上,然后在調用 Logic 時發生。

作為跟進,我也嘗試了這個示例,並在代碼中的可比較位置收到了相同的錯誤。

https://www.red-gate.com/simple-talk/dotnet/net-development/creating-ccli-wrapper/

這是通過以下方式解決的:
A) 刪除並添加回應用程序的 WPF 部分
B) 將 CLI 引用的“Copy Local”屬性設置為 true。

由於缺乏知識,我遵循這些示例的原因是為了更多地了解此過程。 我不認為這是真正的答案,但它確實解決了我眼前的問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM